> (-2 * bitCounter & 6)
);
}
}
return output;
};
// `encode` is designed to be fully compatible with `btoa` as described in the
// HTML Standard: http://whatwg.org/html/webappapis.html#dom-windowbase64-btoa
var encode = function(input) {
input = String(input);
if (/[^\0-\xFF]/.test(input)) {
// Note: no need to special-case astral symbols here, as surrogates are
// matched, and the input is supposed to only contain ASCII anyway.
error(
'The string to be encoded contains characters outside of the ' +
'Latin1 range.'
);
}
var padding = input.length % 3;
var output = '';
var position = -1;
var a;
var b;
var c;
var d;
var buffer;
// Make sure any padding is handled outside of the loop.
var length = input.length - padding;
while (++position < length) {
// Read three bytes, i.e. 24 bits.
a = input.charCodeAt(position) << 16;
b = input.charCodeAt(++position) << 8;
c = input.charCodeAt(++position);
buffer = a + b + c;
// Turn the 24 bits into four chunks of 6 bits each, and append the
// matching character for each of them to the output.
output += (
TABLE.charAt(buffer >> 18 & 0x3F) +
TABLE.charAt(buffer >> 12 & 0x3F) +
TABLE.charAt(buffer >> 6 & 0x3F) +
TABLE.charAt(buffer & 0x3F)
);
}
if (padding == 2) {
a = input.charCodeAt(position) << 8;
b = input.charCodeAt(++position);
buffer = a + b;
output += (
TABLE.charAt(buffer >> 10) +
TABLE.charAt((buffer >> 4) & 0x3F) +
TABLE.charAt((buffer << 2) & 0x3F) +
'='
);
} else if (padding == 1) {
buffer = input.charCodeAt(position);
output += (
TABLE.charAt(buffer >> 2) +
TABLE.charAt((buffer << 4) & 0x3F) +
'=='
);
}
return output;
};
var base64 = {
'encode': encode,
'decode': decode,
'version': '0.1.0'
};
// Some AMD build optimizers, like r.js, check for specific condition patterns
// like the following:
if (
true
) {
!(__WEBPACK_AMD_DEFINE_RESULT__ = function() {
return base64;
}.call(exports, __webpack_require__, exports, module),
__WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
} else if (freeExports && !freeExports.nodeType) {
if (freeModule) { // in Node.js or RingoJS v0.8.0+
freeModule.exports = base64;
} else { // in Narwhal or RingoJS v0.7.0-
for (var key in base64) {
base64.hasOwnProperty(key) && (freeExports[key] = base64[key]);
}
}
} else { // in Rhino or a web browser
root.base64 = base64;
}
}(this));
/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(273)(module), __webpack_require__(274)))
/***/ }),
/* 273 */
/***/ (function(module, exports) {
module.exports = function(module) {
if(!module.webpackPolyfill) {
module.deprecate = function() {};
module.paths = [];
// module.parent = undefined by default
if(!module.children) module.children = [];
Object.defineProperty(module, "loaded", {
enumerable: true,
get: function() {
return module.l;
}
});
Object.defineProperty(module, "id", {
enumerable: true,
get: function() {
return module.i;
}
});
module.webpackPolyfill = 1;
}
return module;
};
/***/ }),
/* 274 */
/***/ (function(module, exports) {
var g;
// This works in non-strict mode
g = (function() {
return this;
})();
try {
// This works if eval is allowed (see CSP)
g = g || Function("return this")() || (1,eval)("this");
} catch(e) {
// This works if the window reference is available
if(typeof window === "object")
g = window;
}
// g can still be undefined, but nothing to do about it...
// We return undefined, instead of nothing here, so it's
// easier to handle this case. if(!global) { ...}
module.exports = g;
/***/ }),
/* 275 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
var __WEBPACK_AMD_DEFINE_RESULT__;
!(__WEBPACK_AMD_DEFINE_RESULT__ = function () {
var linearGradient = "\n \n \n \n \n \n \n \n \n \n ";
var bar = "\n \n ";
var donut = "\n \n ";
var line = "\n \n ";
var stackedArea = "\n \n ";
return {
bar: bar,
donut: donut,
line: line,
stackedArea: stackedArea
};
}.call(exports, __webpack_require__, exports, module),
__WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
/***/ }),
/* 276 */,
/* 277 */,
/* 278 */,
/* 279 */,
/* 280 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
var __WEBPACK_AMD_DEFINE_RESULT__;
!(__WEBPACK_AMD_DEFINE_RESULT__ = function (require) {
'use strict';
var d3Format = __webpack_require__(28);
var idCounter = 0;
var integerValueFormats = {
small: {
limit: 10,
format: d3Format.format('')
},
medium: {
limit: 1000,
format: d3Format.format('')
},
large: {
limit: null,
format: d3Format.format('.2s')
}
};
var decimalValueFormats = {
small: {
limit: 10,
format: d3Format.format('.3f')
},
medium: {
limit: 100,
format: d3Format.format('.1f')
},
large: {
limit: null,
format: d3Format.format('.2s')
}
};
/**
* Return a relative size for the value given, based in our decimal or integer tables
* @param {Number} value Value to assess its relative size
* @param {Object} limits Object stablishing the limits and formats
* to consider the value of a given size
*/
var getValueSize = function getValueSize(value, limits) {
var size = 'large';
if (value < limits.small.limit) {
size = 'small';
} else if (value < limits.medium.limit) {
size = 'medium';
}
return size;
};
/**
* Calculates percentage of value from total
* @param {Number} value Value to check
* @param {Number} total Sum of values
* @param {String} decimals Specifies number of decimals https://github.com/d3/d3-format
* @return {String} Percentage
*/
var calculatePercent = function calculatePercent(value, total, decimals) {
var percent = total ? value / total * 100 : 0;
return d3Format.format(decimals)(percent);
};
/**
* Checks if a number is an integer or a decimal value
* @param {Number} value Value to check
* @return {Boolean} If it is an iteger
*/
var isInteger = function isInteger(value) {
return value % 1 === 0;
};
/**
* Formats a floating point value depending on its value range
* @param {Number} value Decimal point value to format
* @return {Number} Formatted value to show
*/
var formatDecimalValue = function formatDecimalValue(value) {
var size = getValueSize(value, decimalValueFormats);
var format = decimalValueFormats[size].format;
return format(value);
};
/**
* Formats an integer value depending on its value range
* @param {Number} value Decimal point value to format
* @return {Number} Formatted value to show
*/
var formatIntegerValue = function formatIntegerValue(value) {
var size = getValueSize(value, integerValueFormats);
var format = integerValueFormats[size].format;
return format(value);
};
/**
* Generates a unique id with a prefix
* @param {String} prefix Prefix to add before the id
* @return {String} Unique id
*/
var uniqueId = function uniqueId(prefix) {
var id = ++idCounter;
return prefix.toString() + '-' + id;
};
return {
calculatePercent: calculatePercent,
isInteger: isInteger,
formatDecimalValue: formatDecimalValue,
formatIntegerValue: formatIntegerValue,
uniqueId: uniqueId
};
}.call(exports, __webpack_require__, exports, module),
__WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
/***/ }),
/* 281 */,
/* 282 */,
/* 283 */,
/* 284 */,
/* 285 */,
/* 286 */,
/* 287 */,
/* 288 */,
/* 289 */,
/* 290 */,
/* 291 */,
/* 292 */,
/* 293 */,
/* 294 */,
/* 295 */,
/* 296 */,
/* 297 */,
/* 298 */,
/* 299 */,
/* 300 */,
/* 301 */,
/* 302 */,
/* 303 */,
/* 304 */,
/* 305 */,
/* 306 */,
/* 307 */,
/* 308 */,
/* 309 */,
/* 310 */,
/* 311 */,
/* 312 */,
/* 313 */,
/* 314 */,
/* 315 */,
/* 316 */,
/* 317 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
var __WEBPACK_AMD_DEFINE_RESULT__;
var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; };
function _toConsumableArray(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } else { return Array.from(arr); } }
!(__WEBPACK_AMD_DEFINE_RESULT__ = function (require) {
'use strict';
var d3Array = __webpack_require__(4);
var d3Ease = __webpack_require__(72);
var d3Scale = __webpack_require__(229);
var d3Shape = __webpack_require__(107);
var d3Selection = __webpack_require__(3);
var d3Transition = __webpack_require__(110);
var _require = __webpack_require__(270),
exportChart = _require.exportChart;
var colorHelper = __webpack_require__(106);
var _require2 = __webpack_require__(275),
stackedAreaLoadingMarkup = _require2.stackedArea;
var _require3 = __webpack_require__(280),
uniqueId = _require3.uniqueId;
var DEFAULT_TITLE_TEXT_STYLE = {
'font-size': '22px',
'font-family': 'sans-serif',
'font-style': 'normal',
'font-weight': 0
/**
* @typedef SparklineChartData
* @type {Object[]}
* @property {Number} value Value of the group (required)
* @property {String} name Name of the group (required)
*
* @example
* [
* {
* value: 1,
* date: '2011-01-06T00:00:00Z'
* },
* {
* value: 2,
* date: '2011-01-07T00:00:00Z'
* }
* ]
*/
/**
* Sparkline Chart reusable API module that allows us
* rendering a sparkline configurable chart.
*
* @module Sparkline
* @tutorial sparkline
* @requires d3
*
* @example
* var sparkLineChart = sparkline();
*
* sparkLineChart
* .width(200)
* .height(100);
*
* d3Selection.select('.css-selector')
* .datum(dataset)
* .call(sparkLineChart);
*
*/
};return function module() {
var margin = {
left: 5,
right: 5,
top: 5,
bottom: 5
},
width = 100,
height = 30,
loadingState = stackedAreaLoadingMarkup,
xScale = void 0,
yScale = void 0,
areaGradient = ['#F5FDFF', '#F6FEFC'],
areaGradientEl = void 0,
areaGradientId = uniqueId('sparkline-area-gradient'),
lineStrokeWidth = 2,
lineGradient = colorHelper.colorGradients.greenBlue,
lineGradientEl = void 0,
lineGradientId = uniqueId('sparkline-line-gradient'),
maskingClip = void 0,
maskingClipId = uniqueId('maskingClip'),
svg = void 0,
chartWidth = void 0,
chartHeight = void 0,
data = void 0,
hasArea = true,
isAnimated = false,
clipDuration = 3000,
ease = d3Ease.easeQuadInOut,
topLine = void 0,
area = void 0,
circle = void 0,
titleEl = void 0,
titleText = void 0,
titleTextStyle = DEFAULT_TITLE_TEXT_STYLE,
markerSize = 1.5,
valueLabel = 'value',
dateLabel = 'date',
// getters
getDate = function getDate(_ref) {
var date = _ref.date;
return date;
},
getValue = function getValue(_ref2) {
var value = _ref2.value;
return value;
};
/**
* This function creates the graph using the selection and data provided
*
* @param {D3Selection} _selection A d3 selection that represents
* the container(s) where the chart(s) will be rendered
* @param {SparklineChartData} _data The data to attach and generate the chart
*/
function exports(_selection) {
_selection.each(function (_data) {
chartWidth = width - margin.left - margin.right;
chartHeight = height - margin.top - margin.bottom;
data = cleanData(_data);
buildScales();
buildSVG(this);
createGradients();
createMaskingClip();
drawArea();
drawLine();
drawEndMarker();
if (titleText) {
drawSparklineTitle();
}
});
}
/**
* Builds containers for the chart, the axis and a wrapper for all of them
* NOTE: The order of drawing of this group elements is really important,
* as everything else will be drawn on top of them
* @private
*/
function buildContainerGroups() {
var container = svg.append('g').classed('container-group', true).attr('transform', 'translate(' + margin.left + ',' + margin.top + ')');
container.append('g').classed('text-group', true);
container.append('g').classed('chart-group', true);
container.append('g').classed('metadata-group', true);
}
/**
* Creates the x, y and color scales of the chart
* @private
*/
function buildScales() {
xScale = d3Scale.scaleLinear().domain(d3Array.extent(data, getDate)).range([0, chartWidth]);
yScale = d3Scale.scaleLinear().domain(d3Array.extent(data, getValue)).range([chartHeight, 0]);
}
/**
* Builds the SVG element that will contain the chart
* @param {HTMLElement} container DOM element that will work as the container of the graph
* @private
*/
function buildSVG(container) {
if (!svg) {
svg = d3Selection.select(container).append('svg').classed('britechart sparkline', true);
buildContainerGroups();
}
svg.attr('width', width).attr('height', height);
}
/**
* Cleaning data casting the values and dates to the proper type while keeping
* the rest of properties on the data
* @param {SparklineChartData} originalData Raw data from the container
* @return {SparklineChartData} Clean data
* @private
*/
function cleanData(originalData) {
return originalData.reduce(function (acc, d) {
d.date = new Date(d[dateLabel]);
d.value = +d[valueLabel];
return [].concat(_toConsumableArray(acc), [d]);
}, []);
}
/**
* Creates the gradient on the area below the line
* @return {void}
*/
function createGradients() {
var metadataGroup = svg.select('.metadata-group');
if (areaGradientEl || lineGradientEl) {
svg.selectAll('#' + areaGradientId).remove();
svg.selectAll('#' + lineGradientId).remove();
}
areaGradientEl = metadataGroup.append('linearGradient').attr('id', areaGradientId).attr('class', 'area-gradient').attr('gradientUnits', 'userSpaceOnUse').attr('x1', 0).attr('x2', xScale(data[data.length - 1].date)).attr('y1', 0).attr('y2', 0).selectAll('stop').data([{ offset: '0%', color: areaGradient[0] }, { offset: '100%', color: areaGradient[1] }]).enter().append('stop').attr('offset', function (_ref3) {
var offset = _ref3.offset;
return offset;
}).attr('stop-color', function (_ref4) {
var color = _ref4.color;
return color;
});
lineGradientEl = metadataGroup.append('linearGradient').attr('id', lineGradientId).attr('class', 'line-gradient').attr('gradientUnits', 'userSpaceOnUse').attr('x1', 0).attr('x2', xScale(data[data.length - 1].date)).attr('y1', 0).attr('y2', 0).selectAll('stop').data([{ offset: '0%', color: lineGradient[0] }, { offset: '100%', color: lineGradient[1] }]).enter().append('stop').attr('offset', function (_ref5) {
var offset = _ref5.offset;
return offset;
}).attr('stop-color', function (_ref6) {
var color = _ref6.color;
return color;
});
}
/**
* Creates a masking clip that would help us fake an animation if the
* proper flag is true
*
* @return {void}
*/
function createMaskingClip() {
if (maskingClip) {
svg.selectAll('#' + maskingClipId).remove();
}
if (isAnimated) {
maskingClip = svg.select('.metadata-group').append('clipPath').attr('id', maskingClipId).attr('class', 'clip-path').append('rect').attr('width', 0).attr('height', height);
d3Selection.select('#' + maskingClipId + ' rect').transition().ease(ease).duration(clipDuration).attr('width', width);
}
}
/**
* Draws the area that will be placed below the line
* @private
*/
function drawArea() {
if (area) {
svg.selectAll('.sparkline-area').remove();
}
area = d3Shape.area().x(function (_ref7) {
var date = _ref7.date;
return xScale(date);
}).y0(function () {
return yScale(0) + lineStrokeWidth / 2;
}).y1(function (_ref8) {
var value = _ref8.value;
return yScale(value);
}).curve(d3Shape.curveBasis);
svg.select('.chart-group').append('path').datum(data).attr('class', 'sparkline-area').attr('fill', 'url(#' + areaGradientId + ')').attr('d', area).attr('clip-path', 'url(#' + maskingClipId + ')');
}
/**
* Draws the line element within the chart group
* @private
*/
function drawLine() {
if (topLine) {
svg.selectAll('.line').remove();
}
topLine = d3Shape.line().curve(d3Shape.curveBasis).x(function (_ref9) {
var date = _ref9.date;
return xScale(date);
}).y(function (_ref10) {
var value = _ref10.value;
return yScale(value);
});
svg.select('.chart-group').append('path').datum(data).attr('class', 'line').attr('stroke', 'url(#' + lineGradientId + ')').attr('d', topLine).attr('clip-path', 'url(#' + maskingClipId + ')');
}
/**
* Draws the text element within the text group
* Is displayed at the top of sparked area
* @private
*/
function drawSparklineTitle() {
if (titleEl) {
svg.selectAll('.sparkline-text').remove();
}
titleEl = svg.selectAll('.text-group').append('text').attr('x', chartWidth / 2).attr('y', chartHeight / 6).attr('text-anchor', 'middle').attr('class', 'sparkline-text').style('font-size', titleTextStyle['font-size'] || DEFAULT_TITLE_TEXT_STYLE['font-size']).style('fill', titleTextStyle['fill'] || lineGradient[0]).style('font-family', titleTextStyle['font-family'] || DEFAULT_TITLE_TEXT_STYLE['font-family']).style('font-weight', titleTextStyle['font-weight'] || DEFAULT_TITLE_TEXT_STYLE['font-weight']).style('font-style', titleTextStyle['font-style'] || DEFAULT_TITLE_TEXT_STYLE['font-style']).text(titleText);
}
/**
* Draws a marker at the end of the sparkline
*/
function drawEndMarker() {
if (circle) {
svg.selectAll('.sparkline-circle').remove();
}
circle = svg.selectAll('.chart-group').append('circle').attr('class', 'sparkline-circle').attr('cx', xScale(data[data.length - 1].date)).attr('cy', yScale(data[data.length - 1].value)).attr('r', markerSize);
}
// API
/**
* Gets or Sets the areaGradient of the chart
* @param {String[]} _x Desired areaGradient for the graph
* @return {areaGradient | module} Current areaGradient or Chart module to chain calls
* @public
*/
exports.areaGradient = function (_x) {
if (!arguments.length) {
return areaGradient;
}
areaGradient = _x;
return this;
};
/**
* Gets or Sets the dateLabel of the chart
* @param {Number} _x Desired dateLabel for the graph
* @return {dateLabel | module} Current dateLabel or Chart module to chain calls
* @public
*/
exports.dateLabel = function (_x) {
if (!arguments.length) {
return dateLabel;
}
dateLabel = _x;
return this;
};
/**
* Gets or Sets the duration of the animation
* @param {Number} _x Desired animation duration for the graph
* @return {dateLabel | module} Current animation duration or Chart module to chain calls
* @public
*/
exports.duration = function (_x) {
if (!arguments.length) {
return clipDuration;
}
clipDuration = _x;
return this;
};
/**
* Chart exported to png and a download action is fired
* @param {String} filename File title for the resulting picture
* @param {String} title Title to add at the top of the exported picture
* @public
*/
exports.exportChart = function (filename, title) {
exportChart.call(exports, svg, filename, title);
};
/**
* Gets or Sets the height of the chart
* @param {Number} _x Desired width for the graph
* @return { height | module} Current height or Chart module to chain calls
* @public
*/
exports.height = function (_x) {
if (!arguments.length) {
return height;
}
height = _x;
return this;
};
/**
* Gets or Sets the isAnimated property of the chart, making it to animate when render.
* By default this is 'false'
*
* @param {Boolean} _x Desired animation flag
* @return {isAnimated | module} Current isAnimated flag or Chart module
* @public
*/
exports.isAnimated = function (_x) {
if (!arguments.length) {
return isAnimated;
}
isAnimated = _x;
return this;
};
/**
* Gets or Sets the lineGradient of the chart
* @param {String[]} _x Desired lineGradient for the graph
* @return {lineGradient | module} Current lineGradient or Chart module to chain calls
* @public
*/
exports.lineGradient = function (_x) {
if (!arguments.length) {
return lineGradient;
}
lineGradient = _x;
return this;
};
/**
* Gets or Sets the loading state of the chart
* @param {string} markup Desired markup to show when null data
* @return {loadingState | module} Current loading state markup or Chart module to chain calls
* @public
*/
exports.loadingState = function (_markup) {
if (!arguments.length) {
return loadingState;
}
loadingState = _markup;
return this;
};
/**
* Gets or Sets the margin of the chart
* @param {Object} _x Margin object to get/set
* @return {margin | module} Current margin or Chart module to chain calls
* @public
*/
exports.margin = function (_x) {
if (!arguments.length) {
return margin;
}
margin = _extends({}, margin, _x);
return this;
};
/**
* Gets or Sets the text of the title at the top of sparkline.
* To style the title, use the titleTextStyle method below.
* @param {String} _x String to set
* @return {String | module} Current titleText or Chart module to chain calls
* @public
*/
exports.titleText = function (_x) {
if (!arguments.length) {
return titleText;
}
titleText = _x;
return this;
};
/**
* Gets or Sets the text style object of the title at the top of sparkline.
* Using this method, you can set font-family, font-size, font-weight, font-style,
* and color (fill). The default text font settings:
*
*
*
* {
* 'font-family': 'sans-serif',
* 'font-size': '22px',
* 'font-weight': 0,
* 'font-style': 'normal',
* 'fill': linearGradient[0]
* }
*
*
*
* You can set attributes individually. Setting just 'font-family'
* within the object will set custom 'font-family` while the rest
* of the attributes will have the default values provided above.
* @param {Object} _x Object with text font configurations
* @return {Object | module} Current titleTextStyle or Chart module to chain calls
* @public
* @example
* sparkline.titleTextStyle({
* 'font-family': 'Roboto',
* 'font-size': '1.5em',
* 'font-weight': 600,
* 'font-style': 'italic',
* 'fill': 'lightblue'
* })
*/
exports.titleTextStyle = function (_x) {
if (!arguments.length) {
return titleTextStyle;
}
titleTextStyle = _x;
return this;
};
/**
* Gets or Sets the valueLabel of the chart
* @param {Number} _x Desired valueLabel for the graph
* @return {valueLabel | module} Current valueLabel or Chart module to chain calls
* @public
*/
exports.valueLabel = function (_x) {
if (!arguments.length) {
return valueLabel;
}
valueLabel = _x;
return this;
};
/**
* Gets or Sets the width of the chart
* @param {Number} _x Desired width for the graph
* @return {width | module} Current width or Chart module to chain calls
* @public
*/
exports.width = function (_x) {
if (!arguments.length) {
return width;
}
width = _x;
return this;
};
return exports;
};
}.call(exports, __webpack_require__, exports, module),
__WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
/***/ })
/******/ ]);
});
//# sourceMappingURL=sparkline.min.js.map