sleek_charts 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 7391ad7d984d32aed098dc84c9cacd8e2e67bd76
4
+ data.tar.gz: 5c1bc0324d6aa3f898673b968e883b7ac3ef9d52
5
+ SHA512:
6
+ metadata.gz: fa977e8d6e25cacabfce7f96ccb1a34696f79c65838a325fe4a2e22a462ecca4021e6be68b7df01e7a42089ceda316ee7d05a86717c4f089b229c929ef9ee36e
7
+ data.tar.gz: 288931d0d01727e6421b78c62c7d193ca5294453aa7661cf633f4de21950f8e7cdf8a1e79d0e400fc3c8b30cf15def591652cfc348f1adb408384cbc1fc6fa74
data/.gitignore ADDED
@@ -0,0 +1,17 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in sleek_charts.gemspec
4
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2013 Gourav Tiwari
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,46 @@
1
+ # SleekCharts
2
+
3
+ Provides Bar and Donut charts with consitent tooltip for Rails applications.
4
+
5
+ ## Supports Rails 3.1+
6
+
7
+ ## Installation
8
+
9
+ Add this line to your application's Gemfile:
10
+
11
+ gem 'sleek_charts'
12
+
13
+ And then execute:
14
+
15
+ $ bundle
16
+
17
+ Or install it yourself as:
18
+
19
+ $ gem install sleek_charts
20
+
21
+ Once done, add below to application's assets/javascripts/application.js file
22
+ //= require sleek_charts
23
+
24
+ Also, add below to application's assets/stylesheets/application.css file
25
+ *= require sleek_charts
26
+
27
+ ## Usage
28
+
29
+ Simply add bar chart to any element, e.g.
30
+
31
+ barTip(options);
32
+ //where options is a map, checkout bar-tip.js
33
+
34
+ or add donut chart to any element, e.g.
35
+
36
+ donutTip(options);
37
+ //where options is a map, checkout donut-tip.js
38
+
39
+
40
+ ## Contributing
41
+
42
+ 1. Fork it
43
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
44
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
45
+ 4. Push to the branch (`git push origin my-new-feature`)
46
+ 5. Create new Pull Request
data/Rakefile ADDED
@@ -0,0 +1 @@
1
+ require "bundler/gem_tasks"
@@ -0,0 +1,125 @@
1
+ // options: it is a map, which accepts below values
2
+ //
3
+ // selector: selector to which bar chart will be added, default is 'body'
4
+ // e.g. 'div#bar-chart'
5
+ // data: data in JSON object, which contains label and value to create bar chart
6
+ // e.g. [{'label': 'weather-day', 'value': 35.1}, {'label': 'weather-night', 'value': 30.2}]
7
+ // width: width of svg element
8
+ // height: height of svg element
9
+ // margin: margin of svg element and accepts in a map
10
+ // {top: 10, right: 20, bottom: 20, left:10}
11
+ // flexRight: set it to false, when you are ok to display wider column, when there are <5-6 columns, default is true
12
+ // labelAngle: default is 0
13
+ // xDomain: x-axis domain, default is 'label'
14
+ // yDomain: y-axis domain, default is 'value'
15
+ // yAxisText: add additional text on y-axis default is ''
16
+ // tipLabel: tipText which you want to display in tip, default is ''
17
+ // tipValue: tipValue, for each bar, default is 'value'
18
+ // tipText: tipText which you want to display with 'label' and 'value', default is ''
19
+
20
+ function mergeConfigOptions(defaults,options){
21
+ var mergedConfig = {};
22
+ for (var attrname in defaults) { mergedConfig[attrname] = defaults[attrname]; }
23
+ for (var attrname in options) { mergedConfig[attrname] = options[attrname]; }
24
+ return mergedConfig;
25
+ }
26
+
27
+ function barTip(options){
28
+ var defaults = {
29
+ selector: 'body',
30
+ data: [{'label': 'weather-morning', 'value': 29.1}, {'label': 'weather-afternoon', 'value': 33.2},
31
+ {'label': 'weather-evening', 'value': 32.1}, {'label': 'weather-night', 'value': 30.2}],
32
+ width: 600,
33
+ height: 400,
34
+ margin: {top: 10, right: 20, bottom: 20, left:10},
35
+ flexRight: true,
36
+ labelAngle: -30,
37
+ xDomain: 'label',
38
+ yDomain: 'value',
39
+ yAxisText: '',
40
+ tipLabel: '',
41
+ tipValue: 'value',
42
+ tipText: ''
43
+ };
44
+
45
+ var config = (options) ? mergeConfigOptions(defaults,options) : defaults;
46
+
47
+ var data = config.data;
48
+
49
+ // Just to make sure the chart doesn't look clutter, when there are < 5-6 columns
50
+ if(config.flexRight){
51
+ config.margin['right'] = d3.max([20, (config.width - data.length * 50)]);
52
+ }
53
+
54
+ var margin = config.margin,
55
+ width = config.width - margin.left - margin.right,
56
+ height = config.height - margin.top - margin.bottom;
57
+
58
+ var x = d3.scale.ordinal()
59
+ .rangeRoundBands([0, width], .1);
60
+
61
+ var y = d3.scale.linear()
62
+ .range([height, 0]);
63
+
64
+ var xAxis = d3.svg.axis()
65
+ .scale(x)
66
+ .orient("bottom");
67
+
68
+ var yAxis = d3.svg.axis()
69
+ .scale(y)
70
+ .orient("left");
71
+
72
+ var svg = d3.select(config.selector).append("svg")
73
+ .attr("width", config.width)
74
+ .attr("height", config.height)
75
+ .append("g")
76
+ .attr("transform", "translate(" + margin.left + "," + margin.top + ")");
77
+
78
+ var tip = d3.tip()
79
+ .attr('class', 'd3-tip')
80
+ .offset([-10, 0])
81
+ .html(function(d) {
82
+ label = d[config.tipLabel] == undefined ? "" : " " + d[config.tipLabel];
83
+
84
+ return "<strong>" + config.tipText + label + "</strong> <span style='color:red'>" + d[config.tipValue] + "</span>";
85
+ });
86
+ console.log(svg);
87
+ svg.call(tip);
88
+
89
+ x.domain(data.map(function(d) { return d[config.xDomain]; }));
90
+ y.domain([0, d3.max(data, function(d) { return d[config.yDomain]; })]);
91
+
92
+ svg.append("g")
93
+ .attr("class", "x axis")
94
+ .attr("transform", "translate(0," + height + ")")
95
+ .call(xAxis)
96
+ .selectAll("text")
97
+ .style("text-anchor", "end")
98
+ .attr("dx", "-.8em")
99
+ .attr("dy", ".15em")
100
+ .attr("transform", function(d) {
101
+ return "rotate("+ config.labelAngle +")" ;
102
+ });
103
+
104
+ svg.append("g")
105
+ .attr("class", "y axis")
106
+ .call(yAxis)
107
+ .append("text")
108
+ .attr("transform", "rotate(-90)")
109
+ .attr("y", -40)
110
+ .attr("x", -80)
111
+ .attr("dy", "0.71em")
112
+ .style("text-anchor", "end")
113
+ .text(config.yAxisText);
114
+
115
+ svg.selectAll(".bar")
116
+ .data(data)
117
+ .enter().append("rect")
118
+ .attr("class", "bar")
119
+ .attr("x", function(d) { return x(d[config.xDomain]); })
120
+ .attr("width", x.rangeBand())
121
+ .attr("y", function(d) { return y(d[config.yDomain]); })
122
+ .attr("height", function(d) { return height - y(d[config.yDomain]); })
123
+ .on('mouseover', tip.show)
124
+ .on('mouseout', tip.hide);
125
+ }
@@ -0,0 +1,6 @@
1
+ function mergeConfigOptions(defaults,options){
2
+ var mergedConfig = {};
3
+ for (var attrname in defaults) { mergedConfig[attrname] = defaults[attrname]; }
4
+ for (var attrname in options) { mergedConfig[attrname] = options[attrname]; }
5
+ return mergedConfig;
6
+ }
@@ -0,0 +1,276 @@
1
+ // d3.tip
2
+ // Copyright (c) 2013 Justin Palmer
3
+ //
4
+ // Tooltips for d3.js SVG visualizations
5
+
6
+ // Public - contructs a new tooltip
7
+ //
8
+ // Returns a tip
9
+ d3.tip = function() {
10
+ var direction = d3_tip_direction,
11
+ offset = d3_tip_offset,
12
+ html = d3_tip_html,
13
+ node = initNode(),
14
+ svg = null,
15
+ point = null
16
+
17
+ function tip(vis) {
18
+ svg = getSVGNode(vis)
19
+ point = svg.createSVGPoint()
20
+ document.body.appendChild(node)
21
+ }
22
+
23
+ // Public - show the tooltip on the screen
24
+ //
25
+ // Returns a tip
26
+ tip.show = function() {
27
+ var content = html.apply(this, arguments),
28
+ poffset = offset.apply(this, arguments),
29
+ dir = direction.apply(this, arguments),
30
+ nodel = d3.select(node), i = 0,
31
+ coords
32
+
33
+ nodel.html(content)
34
+ .style({ opacity: 1, 'pointer-events': 'all' })
35
+
36
+ while(i--) nodel.classed(directions[i], false)
37
+ coords = direction_callbacks.get(dir).apply(this)
38
+ nodel.classed(dir, true).style({
39
+ top: (coords.top + poffset[0]) + 'px',
40
+ left: (coords.left + poffset[1]) + 'px'
41
+ })
42
+
43
+ return tip
44
+ }
45
+
46
+ // Public - hide the tooltip
47
+ //
48
+ // Returns a tip
49
+ tip.hide = function() {
50
+ nodel = d3.select(node)
51
+ nodel.style({ opacity: 0, 'pointer-events': 'none' })
52
+ return tip
53
+ }
54
+
55
+ // Public: Proxy attr calls to the d3 tip container. Sets or gets attribute value.
56
+ //
57
+ // n - name of the attribute
58
+ // v - value of the attribute
59
+ //
60
+ // Returns tip or attribute value
61
+ tip.attr = function(n, v) {
62
+ if (arguments.length < 2 && typeof n === 'string') {
63
+ return d3.select(node).attr(n)
64
+ } else {
65
+ var args = Array.prototype.slice.call(arguments)
66
+ d3.selection.prototype.attr.apply(d3.select(node), args)
67
+ }
68
+
69
+ return tip
70
+ }
71
+
72
+ // Public: Proxy style calls to the d3 tip container. Sets or gets a style value.
73
+ //
74
+ // n - name of the property
75
+ // v - value of the property
76
+ //
77
+ // Returns tip or style property value
78
+ tip.style = function(n, v) {
79
+ if (arguments.length < 2 && typeof n === 'string') {
80
+ return d3.select(node).style(n)
81
+ } else {
82
+ var args = Array.prototype.slice.call(arguments)
83
+ d3.selection.prototype.style.apply(d3.select(node), args)
84
+ }
85
+
86
+ return tip
87
+ }
88
+
89
+ // Public: Set or get the direction of the tooltip
90
+ //
91
+ // v - One of n(north), s(south), e(east), or w(west), nw(northwest),
92
+ // sw(southwest), ne(northeast) or se(southeast)
93
+ //
94
+ // Returns tip or direction
95
+ tip.direction = function(v) {
96
+ if (!arguments.length) return direction
97
+ direction = v == null ? v : d3.functor(v)
98
+
99
+ return tip
100
+ }
101
+
102
+ // Public: Sets or gets the offset of the tip
103
+ //
104
+ // v - Array of [x, y] offset
105
+ //
106
+ // Returns offset or
107
+ tip.offset = function(v) {
108
+ if (!arguments.length) return offset
109
+ offset = v == null ? v : d3.functor(v)
110
+
111
+ return tip
112
+ }
113
+
114
+ // Public: sets or gets the html value of the tooltip
115
+ //
116
+ // v - String value of the tip
117
+ //
118
+ // Returns html value or tip
119
+ tip.html = function(v) {
120
+ if (!arguments.length) return html
121
+ html = v == null ? v : d3.functor(v)
122
+
123
+ return tip
124
+ }
125
+
126
+ function d3_tip_direction() { return 'n' }
127
+ function d3_tip_offset() { return [0, 0] }
128
+ function d3_tip_html() { return ' ' }
129
+
130
+ var direction_callbacks = d3.map({
131
+ n: direction_n,
132
+ s: direction_s,
133
+ e: direction_e,
134
+ w: direction_w,
135
+ nw: direction_nw,
136
+ ne: direction_ne,
137
+ sw: direction_sw,
138
+ se: direction_se
139
+ }),
140
+
141
+ directions = direction_callbacks.keys()
142
+
143
+ function direction_n() {
144
+ var bbox = getScreenBBox()
145
+ return {
146
+ top: bbox.n.y - node.offsetHeight,
147
+ left: bbox.n.x - node.offsetWidth / 2
148
+ }
149
+ }
150
+
151
+ function direction_s() {
152
+ var bbox = getScreenBBox()
153
+ return {
154
+ top: bbox.s.y,
155
+ left: bbox.s.x - node.offsetWidth / 2
156
+ }
157
+ }
158
+
159
+ function direction_e() {
160
+ var bbox = getScreenBBox()
161
+ return {
162
+ top: bbox.e.y - node.offsetHeight / 2,
163
+ left: bbox.e.x
164
+ }
165
+ }
166
+
167
+ function direction_w() {
168
+ var bbox = getScreenBBox()
169
+ return {
170
+ top: bbox.w.y - node.offsetHeight / 2,
171
+ left: bbox.w.x - node.offsetWidth
172
+ }
173
+ }
174
+
175
+ function direction_nw() {
176
+ var bbox = getScreenBBox()
177
+ return {
178
+ top: bbox.nw.y - node.offsetHeight,
179
+ left: bbox.nw.x - node.offsetWidth
180
+ }
181
+ }
182
+
183
+ function direction_ne() {
184
+ var bbox = getScreenBBox()
185
+ return {
186
+ top: bbox.ne.y - node.offsetHeight,
187
+ left: bbox.ne.x
188
+ }
189
+ }
190
+
191
+ function direction_sw() {
192
+ var bbox = getScreenBBox()
193
+ return {
194
+ top: bbox.sw.y,
195
+ left: bbox.sw.x - node.offsetWidth
196
+ }
197
+ }
198
+
199
+ function direction_se() {
200
+ var bbox = getScreenBBox()
201
+ return {
202
+ top: bbox.se.y,
203
+ left: bbox.e.x
204
+ }
205
+ }
206
+
207
+ function initNode() {
208
+ var node = d3.select(document.createElement('div'))
209
+ node.style({
210
+ position: 'absolute',
211
+ opacity: 0,
212
+ pointerEvents: 'none',
213
+ boxSizing: 'border-box'
214
+ })
215
+
216
+ return node.node()
217
+ }
218
+
219
+ function getSVGNode(el) {
220
+ el = el.node()
221
+ if(el.tagName.toLowerCase() == 'svg')
222
+ return el
223
+
224
+ return el.ownerSVGElement
225
+ }
226
+
227
+ // Private - gets the screen coordinates of a shape
228
+ //
229
+ // Given a shape on the screen, will return an SVGPoint for the directions
230
+ // n(north), s(south), e(east), w(west), ne(northeast), se(southeast), nw(northwest),
231
+ // sw(southwest).
232
+ //
233
+ // +-+-+
234
+ // | |
235
+ // + +
236
+ // | |
237
+ // +-+-+
238
+ //
239
+ // Returns an Object {n, s, e, w, nw, sw, ne, se}
240
+ function getScreenBBox() {
241
+ var target = d3.event.target,
242
+ bbox = {},
243
+ matrix = target.getScreenCTM(),
244
+ tbbox = target.getBBox(),
245
+ width = tbbox.width,
246
+ height = tbbox.height,
247
+ x = tbbox.x,
248
+ y = tbbox.y,
249
+ scrollTop = document.documentElement.scrollTop || document.body.scrollTop,
250
+ scrollLeft = document.documentElement.scrollLeft || document.body.scrollLeft
251
+
252
+
253
+ point.x = x + scrollLeft
254
+ point.y = y + scrollTop
255
+ bbox.nw = point.matrixTransform(matrix)
256
+ point.x += width
257
+ bbox.ne = point.matrixTransform(matrix)
258
+ point.y += height
259
+ bbox.se = point.matrixTransform(matrix)
260
+ point.x -= width
261
+ bbox.sw = point.matrixTransform(matrix)
262
+ point.y -= height / 2
263
+ bbox.w = point.matrixTransform(matrix)
264
+ point.x += width
265
+ bbox.e = point.matrixTransform(matrix)
266
+ point.x -= width / 2
267
+ point.y -= height / 2
268
+ bbox.n = point.matrixTransform(matrix)
269
+ point.y += height
270
+ bbox.s = point.matrixTransform(matrix)
271
+
272
+ return bbox
273
+ }
274
+
275
+ return tip
276
+ };