I am using c3.js, AngularJs and bootstrap to render some charts. The setup is as follows:
Bind a variable to <select> form to change between chart types
I have a $watch on the same variable which triggers the chart rendering.
Depending on variable I render multiple charts, different types depending on it's value. I have two charts per row, each one inside a col-XX-6.
Each chart group is hidden/shown using ng-show="myVariable== 'typeX'" depending on the same variable that triggers the render.
So, view and c3 render are acting on the same variable.
The first render is triggered by watch on $viewContentLoaded and everything works fine. After I change the select option, the first chart in the column renders with 100% width, disregarding bootstrap template. My theory is that c3.js renders the chart "too fast", before the view kicks in and sets the proper width. Further investigation:
Adding a $timeout on renderer fixes the problem but this is unacceptable solution
Adding a fixed width on charts works but is not acceptable, it needs to adapt to bootstrap
So far it seems that the only solution is to listen to the actual DOM change to see when the DOM actually becomes visible and only then start the render. But it seems that this technique is highly discouraged.
How do I fix this problem the proper way?
Edit 1: It seems that even if I render all the charts once and never refresh them, they still rarely but randomly oversize when shown.
Edit 2:
Plunkr: http://plnkr.co/edit/mU5m694VoDB5GtXrmPdP
Plunkr works (...) but basically, it happens to me when you'd switch from type2 to type1, the first graph would take 100% width and mess up everything. I'll see if I can find something in Plunkr that would make it break.
Edit 3: Well, perhaps not working that well afterall. I noticed charts sometimes do not render (blank page) and they only appear after I inspect element or fiddle with the screen in some way. Seems like it could be the same problem behind this. You should increase the plunker preview to simulate a wider screen.
You mention that you are having problems with initial size, but actually, there is going to be problems when browser size changes too.
We use d3.js (not c3) extensively in our project, and we found that the best option is to set viewBox attribute of svg element created by d3 to the parent element's size when browser size change event is emitted by window.
viewBox basically translates coordinate system of svg to origin and size defined by it.
Related
I've been trying to change the width of a single column in a bar chart created using Highcharts. Here is a codepen.
In all the search that I did, I could only find two solutions given in this question.
The problem with that is that since they are set dinamically after initialization, any action that calls the redraw method will revert their width to the calculated one.
Also, I don't understand why they are using series[0].data[5].graphic.attr('width') and how it affects, since I don't see such property in the object (console screenshot)
Finally, in the codepen I'm also changing the color of the same point, but doing it in the initialization function. I wonder if there is a way to do the same for the width.
Am I missing something? Because I didn't find anything in the API docs and I'm clueless as to how these solutions actually work if there is no such property in the object.
Short explanation:
attr method is inherited from Element class. You can see that method in prototype (in console click __proto__). Method attr works in two ways: attr(property_name) is a getter (to get e.g. width) and attr({ property_name: value }) is a setter (to set e.g. width). If you use source files (.src.js), then you would notice that SVGElement class.
width will change on any redraw event, because it is recalculated again (like updating point, or resizing window). In fact you can use chart.events.redraw and there change width. In fact, I would use both, chart.events.redraw and chart.events.load with one function, to update widths.
And to explain, why you can't set width in point, like you did with color: there is not such option on point level, like pointWidth. You can set specific width for all points within one series only (using mentioned pointWidth). There is an idea for Highcharts, to add such feature (to the core or as a plugin). Feel free to vote for it on the UserVoice. Here is interesting example: http://jsfiddle.net/75oucp3b/14/ (works with v4.1.8)
I've implemented force layout and it's working well. However, the problem is, dragging one element doesn't pull other elements. I didn't assign fixed:true property so that is not the problem.
Here is what I did. As you see, dragging one element doesn't fully affect the others. For example, pulling one node to the right doesn't move the other nodes to the right. But what I want to do is like this example.
I am new to the world of SVG and D3, learning as I implement. Facing an issue with one of the websites that I am currently working on.
Requirement:
We want to create a custom graph (similar to bar graph) that has a set of bars that represent my data points and certain icons are embedded into these bars based on the type of bar graph data. The graph is representing a person's achievements throughout their career. On hover of the bar we show a custom popup that has a brief description of the bar (see below for an example). Some bars have an additional arrow that represents whether the bar is representing an experience that the user is currently pursuing.
Progress so far:
As you can see my profile under TIMELINE section.
So, whats wrong?
Everything works fine (as you can see from the screenshots) on Chrome. All other browsers render the graph without the icons. You can view my profile on Chrome and Firefox.
I copied d3 generated SVG HTML code and pasted it in jsfiddle to test it out on all browsers and found that all browsers are rendering it: (ignore the colors, I have not applied CSS to it, but the icons show up) http://jsfiddle.net/EbpPG/1/
See JS fiddle link
Check my profile to see the graph. The logic to generate the graph can be found in chart.js file, createTimelineChart() function.
Can someone have a look at it and let me know what's the mistake I am making?
The problem is obviously how you dynamically generate the SVG. The path element is generated in the wrong namespace. This typically happens when you're using something like jQuery's append with a string:
$('svg').append('<path d="m0,0 h100"/>')
This will generate an HTML-namespaced path element, which does not exist. (Interestingly, Chromium is not even showing it in the developer tools.)
Firebug is good at showing you problems of this kind. In the HTML panel, the wrongly namespaced elements are shown in a lighter color. Right-clicking on them in the HTML panel gives you the option to examine in the DOM panel, and there you can see what the namespaceURI property is.
So, use either plain DOM manipulation methods or, if you're already using d3 anyway,
d3.select('svg').append('svg:path').attr('d','m0,0 h100')
Check out with Firefox DOM Inspector and you'll see that the path element that forms the icon is in the HTML namespace rather than the SVG namespace which would be required for it to appear.
Are you passing this data though decodeHTMLEntities, that might be recreating the element in the wrong namespace, you'll need to step though with a debugger to see when it goes wrong.
If you save the d3 generated page then when it's reread by any UA it will pick the right namespace which is why the jsfiddle works.
I want this highchart - http://jsfiddle.net/zPDca/ inside a popup. But if i decrease its width to lets say to 200 px, it dissapers. Any suggestions!
It looks like 251 px is the lower limit for the width.
This was probably a decision the developers made due to readability. Think about it:
This is a stock chart and it contains the "detail" view and a navigator view, you have export enabled and by default you are showing the buttons, the default selection buttons for zooming are also shown. Wouldn't this be really crowded for the user? Why not use a different kind of chart (standard highchart maybe) that shows latest data and gives user option to expand view. This would save a lot of space in the view.
Things you can try:
Remove the export buttons (you can write your own extension to still do exporting without useing the built-in buttons)
Remove the "Zoom" text
Change chart to be less "busy" overall
Having a data visualization is all about quickly seeing the data you need - not necessarily seeing all the options you may need in a tight space. If this chart is to be used for continuous monitoring you can strip it of all option settings but have it use the options set by the user in a "primary/setup" chart.
Look this example http://jsfiddle.net/zPDca/1/
It's working well.
If you take a look the reference you can see that it can be calculated by the containing element. So you just have to remove width from your chart as you can see on my example.
Okay I got the answer. Versions higher than 1.1.5 do not allow charts smaller than certain dimension. I do not know why. But I'm detouring right now by using version 1.1.5.
Is there a way to display a component in EditorGridPanel without the need to click on the cell?
The problem I see on this demo is that the checkboxes are not Ext.form.Checkbox components, and not even inherited from it. The checkboxes are simply background images and since I am building a grid that needs ComboBoxes, it will not be simple to apply a similar hack.
Ok, I see what you're after now. Immediately display the combobox on each row upon grid rendering. That might be difficult to achieve, and I suspect it might have a negative effect on the overall performance of the grid (multiple comboboxes to render instead of just one).
In any case, have you looked at the clicksToEdit config option of EditorGridPanel? From ExtJS documentation:
The number of clicks on a cell
required to display the cell's editor
(defaults to 2).
Setting this option to 'auto' means
that mousedown on the selected cell
starts editing that cell.
How about if you tried setting this to 'auto'? That would at least reduce the amount of mouseclicks that the user has to do, before editing starts. Is that what you're really after with this?
(Note that I haven't tried this option myself, so I don't know how well it actually works with Comboboxes.)