diff --git a/app/js/services/tooltip.js b/app/js/services/tooltip.js new file mode 100644 index 00000000..0819ecad --- /dev/null +++ b/app/js/services/tooltip.js @@ -0,0 +1,132 @@ +'use strict'; + +var angular = require('angular'); + +var servicesModule = require('./_index.js'); + +function TooltipService() { + var service = {}; + + var render = function(dest, value, d) { + if (angular.isFunction(value)) { + value = value(d); + } + + if (angular.isElement(value)) { + dest.append(value); + } else { + dest.text(value); + } + + return dest; + }; + + var fill = function(dest, element, count) { + for (var i = 0; i < count; i++) { + dest.append(element.clone()); + } + }; + + service.generator = function(content, options) { + options = options || {}; + + return function(d) { + // partially render content first so we can determine the column count + var columns = 0; + var columnOffset = 0; + var partialContent = []; + + var table = angular.element('
').attr('colspan', columns + columnOffset), + options.title, d); + tr.append(th); + thead.append(tr); + } + + if (options.header) { + var tr = angular.element(' | |||
---|---|---|---|
'), columnOffset); + angular.forEach(options.header, function(title) { + tr.append(render(angular.element(' | '), title, d)); + }); + thead.append(tr); + } + + table.append(thead); + } + + // build the body + var tbody = angular.element(' | ||
');
+ td.addClass('legend-color-guide');
+
+ var div = angular.element(' ');
+ div.css('background-color', options.colors[rowIndex]);
+ td.append(div);
+ tr.append(td);
+
+ fill(tr, angular.element(' '), columnOffset - 1);
+ } else {
+ fill(tr, angular.element(' | '), columnOffset);
+ }
+
+ angular.forEach(row, function(col, i) {
+ var td = render(angular.element(' | '), col, d);
+ if (row.length < columns && i == row.length - 1) {
+ // auto-set colspan for last entry in row
+ td.attr('colspan', columns - i);
+ }
+
+ tr.append(td);
+ });
+
+ tbody.append(tr);
+ });
+ table.append(tbody);
+
+ return table[0].outerHTML;
+ };
+ };
+
+ return service;
+}
+
+servicesModule.service('tooltipService', TooltipService);
diff --git a/test/unit/services/tooltip_spec.js b/test/unit/services/tooltip_spec.js
new file mode 100644
index 00000000..f4946b64
--- /dev/null
+++ b/test/unit/services/tooltip_spec.js
@@ -0,0 +1,79 @@
+describe('TooltipService', function() {
+ var $compile;
+ var tooltipService;
+ var sampleData;
+
+ beforeEach(function() {
+ module('app');
+ module('app.services');
+
+ inject(function($injector) {
+ $compile = $injector.get('$compile');
+ tooltipService = $injector.get('tooltipService');
+ });
+
+ sampleData = {
+ index: 0,
+ value: 0,
+ color: 'green',
+ data: { custom: 123 }
+ };
+ });
+
+ it('should generate a simple tooltip', function() {
+ var generator = tooltipService.generator([['Value']]);
+ var element = angular.element(generator(sampleData))[0];
+
+ expect(element.classList).toContain('osh-tooltip');
+ expect(element.querySelectorAll('tr').length).toEqual(1);
+ expect(element.querySelectorAll('td').length).toEqual(1);
+ expect(element.querySelectorAll('th').length).toEqual(0);
+ });
+
+ it('should generate a tooltip with a header', function() {
+ var generator = tooltipService.generator([
+ ['Value']
+ ], { title: 'test', header: ['column'] });
+
+ var element = angular.element(generator(sampleData))[0];
+
+ expect(element.querySelectorAll('tr').length).toEqual(3);
+ expect(element.querySelectorAll('thead tr').length).toEqual(2);
+ expect(element.querySelectorAll('thead tr')[0].innerText).toEqual('test');
+ expect(element.querySelectorAll('thead tr')[1].innerText).toEqual('column');
+ expect(element.querySelector('tbody tr td').innerText).toEqual('Value');
+ });
+
+ it('should generate a tooltip with custom columns', function() {
+ var generator = tooltipService.generator([
+ ['Value', function(d) { return d.value; }],
+ ['Custom', function(d) { return d.data.custom; }]
+ ]);
+ var element = angular.element(generator(sampleData))[0];
+
+ expect(element.querySelectorAll('tr').length).toEqual(2);
+ expect(element.querySelectorAll('td').length).toEqual(4);
+
+ var rows = element.querySelectorAll('tbody tr');
+ expect(rows[0].children[0].innerText).toEqual('Value');
+ expect(rows[0].children[1].innerText).toEqual('0');
+ expect(rows[1].children[0].innerText).toEqual('Custom');
+ expect(rows[1].children[1].innerText).toEqual('123');
+ });
+
+ it('should generate a tooltip with colors', function() {
+ var generator = tooltipService.generator([
+ ['Value', function(d) { return d.value; }],
+ ['Custom', function(d) { return d.data.custom; }]
+ ], { colors: ['red', 'blue'] });
+ var element = angular.element(generator(sampleData))[0];
+
+ expect(element.querySelectorAll('tr').length).toEqual(2);
+ expect(element.querySelectorAll('td').length).toEqual(6);
+
+ var guides = element.querySelectorAll('td:first-child.legend-color-guide');
+ expect(guides.length).toEqual(2);
+ expect(guides[0].children[0].getAttribute('style')).toEqual('background-color: red;');
+ expect(guides[1].children[0].getAttribute('style')).toEqual('background-color: blue;');
+ });
+});
| |