jquery-kpiwidgets
Version:
Inneractive jQuery widgets for presenting data in a KPI box
279 lines (242 loc) • 12.3 kB
JavaScript
/**
* jQuery Top 3 Items Widget
*
* Author: Guy Ben Shoshan 12/2014.
* Tested: FF 33, Chrome 39, IE 11, Opera 12, Safari 5
*
* Copyright (c) 2017 Inneractive
* Dual licensed under the MIT and GPL licenses:
*
* Depends:
* jquery core 1.11.1 - http://code.jquery.com/jquery-1.11.1.min.js
* jquery ui 1.11 - http://jqueryui.com/resources/download/jquery-ui-1.11.2.zip
*
* Description:
* This widget is intended to present a tabular view of 3 items in a KPI box
*
* options:
* title - widget title - default: ""
* data - items data - JSON Array of up to 3 elements - default []
* name - string
* value - number
* symbol - currency (or any other) symbol that will be placed before the value - default: ""
* trend - trend of value change. "up" / "down" / "flat" - default: ""
* delta - percentage of change. integer - default: 0
*
* example
* [{
* name: "",
* value: "",
* symbol: "",
* trend: "",
* delta: 0
* }, {
* name: "",
* value: "",
* symbol: "",
* trend: "",
* delta: 0
* }, {
* name: "",
* value: "",
* symbol: "",
* trend: "",
* delta: 0
* }]
* - default: 0
*
* footer - text that will appear inside the widget footer - default: ""
* height - widget height in px - default: 148
* width - widget width in px - default: 230
* showDecimalPoint - show 2 digits after the decimal point - default: true
* maxDeltaThreshold - above this number the delta value will not appear - default: 999
* next to the delta symbol (ui considerations)
* clickHandler - click handler that triggers when the widget value - default: null
* is being clicked
*
* style classes:
* --------------------------------------------------------------------------------------------------------------------
* containerStyleClass - style class for the widget container - default: "top-three-kpi-container"
* headerStyleClass - style class for the header - default: "kpi-title"
* headerTextStyleClass - style class for the header text - default: "kpi-title-text"
* nameStyleClass - style class for the item name - default: "top-3-name"
* valueStyleClass - style class for the item value - default: "top-3-value"
* trendUpStyleClass - style class for the trend up img - default: "kpi-trend-up-small"
* trendDownStyleClass - style class for the trend down img - default: "kpi-trend-down-small"
* trendFlatStyleClass - style class for the trend flat img - default: "kpi-trend-flat-small"
* deltaUpStyleClass - style class for the delta up - default: "kpi-delta-up"
* deltaDownStyleClass - style class for the delta down - default: "kpi-delta-down"
* deltaFlatStyleClass - style class for the delta flat - default: "kpi-delta-flat"
* footerStyleClass - style class for the footer - default: "top-3-kpi-footer"
* footerTextStyleClass - style class for the footer text - default: "kpi-footer-text"
*
*
* methods:
* setData(data) - sets the 3 items in the widget object and refreshes the view accordingly
* param - JSON Array
* usage:
* var data = [{
* name: "My App",
* value: 202300,
* symbol: "$",
* trend: "down"
* }, {
* name: "Anothe App of Mine",
* value: 2323444,
* symbol: "$",
* trend: "up"
* }];
*
* kpi1 = $("#topThree1").TopThreeKPI(...);
* kpi1.TopThreeKPI("setData", data);
*
* getData() - gets the value from the widget object
* return - JSON Array
* usage:
* kpi1 = $("#topThree1").TopThreeKPI(...);
* kpi1.TopThreeKPI("getData");
*/
(function ($, undefined) {
$.widget("inneractive.TopThreeKPI", {
// Default options.
options: {
title: "",
data: {},
footer: "",
height: 148,
width: 230,
showDecimalPoint: true,
clickHandler: null,
maxDeltaThreshold: 999,
/* css style classes */
containerStyleClass: "top-three-kpi-container",
headerStyleClass: "kpi-title",
headerTextStyleClass: "kpi-title-text",
nameStyleClass: "top-3-name",
valueStyleClass: "top-3-value",
trendUpStyleClass: "kpi-trend-up-small",
trendDownStyleClass: "kpi-trend-down-small",
trendFlatStyleClass: "kpi-trend-flat-small",
deltaUpStyleClass: "kpi-delta-up",
deltaDownStyleClass: "kpi-delta-down",
deltaFlatStyleClass: "kpi-delta-flat",
footerStyleClass: "top-3-kpi-footer",
footerTextStyleClass: "kpi-footer-text"
},
_create: function () {
var _that = this;
var titleHeight = this.options.height / 4;
var footerHeight = (this.options.footer != "") ? (titleHeight / 2) : 0;
var titleCursor = "";
var dataCursor = (typeof(_that.options.clickHandler) == "function") ? "pointer" : "";
var containerDiv = $('<div/>', {
"height": this.options.height + "px",
"width": this.options.width + "px",
"class": this.options.containerStyleClass
});
var titleDiv = $('<div/>', {
html: "<div class=\"" + this.options.headerTextStyleClass + "\" style=\"cursor:" + titleCursor + ";\">" + this.options.title + "</div>",
"class": this.options.headerStyleClass,
height: titleHeight
});
var dataDiv = this._createDataDiv(dataCursor).click(function () {
if (typeof(_that.options.clickHandler) == "function") {
_that.options.clickHandler.apply()
}
});
var footerDiv = $('<div/>', {
html: "<div class=\"" + this.options.footerTextStyleClass + "\">" + this.options.footer + "</div>",
"class": this.options.footerStyleClass,
height: footerHeight
});
containerDiv.append(titleDiv).append(dataDiv).append(footerDiv);
this.element.append(containerDiv);
},
_createDataDiv: function (dataCursor) {
var titleHeight = this.options.height / 4;
var footerHeight = (this.options.footer != "") ? (titleHeight / 2) : 0;
var dataHeight = this.options.height - titleHeight - footerHeight;
var rowItemHeight = dataHeight / 3;
var deltaThreshold = this.options.maxDeltaThreshold;
var dataDiv = $('<div/>', {
"class": "kpi-data top-three-kpi-data",
height: dataHeight
});
var _that = this;
if(this.options.data.length > 0){
$.each(this.options.data, function (key, value) {
var rowData = value;
var trendClass = _that.options.trendFlatStyleClass;
var deltaClass = _that.options.deltaFlatStyleClass;
if (rowData.trend != "") {
if (rowData.trend == "down") {
trendClass = _that.options.trendDownStyleClass;
deltaClass = _that.options.deltaDownStyleClass;
} else if (rowData.trend == "flat") {
trendClass = _that.options.trendFlatStyleClass;
deltaClass = _that.options.deltaFlatStyleClass;
} else if (rowData.trend == "up") {
trendClass = _that.options.trendUpStyleClass;
deltaClass = _that.options.deltaUpStyleClass;
}
}
var rowDataName = rowData.name;
var rowDataValue = rowData.value;
var rowDataDelta = rowData.delta;
try{
if(rowDataName.length > 14){
rowDataName = rowDataName.substr(0, 14) + "..."
}
}catch(exception){
}
try{
if(rowDataValue % 1 == 0 || !_that.options.showDecimalPoint){
rowDataValue = parseInt(rowDataValue).toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",");
}else{
rowDataValue = parseFloat(rowDataValue).toFixed(2).toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",");
}
}catch(exception){
}
var htmlStr = "<div style=\"height: 100%; width: 100%; display: table;cursor:" + dataCursor + "\">" +
"<div title=\"" + rowData.name + "\" class=\"" + _that.options.nameStyleClass + "\">" + rowDataName + "</div>" +
"<div class=\"" + _that.options.valueStyleClass + "\">" + rowData.symbol + rowDataValue + "</div>";
if(rowDataDelta <= deltaThreshold){ // we dont show the delta, so we dont need to add the the delta title attribute to the div
htmlStr += "<div class=\"" + trendClass + "\" />";
}else{
htmlStr += "<div class=\"" + trendClass + "\" title=\"" + rowDataDelta + "%\" />";
}
if(rowDataDelta > 0 && rowDataDelta <= deltaThreshold){
htmlStr += "<div class=\"" + deltaClass + "\">" + rowDataDelta + "%</div>";
}else if(rowDataDelta > deltaThreshold){
htmlStr += "<div class=\"" + deltaClass + "\" style=\"width:20px;\"></div>";
}
htmlStr += "</div>";
var rowItemDiv = $('<div/>', {
"html": htmlStr,
"height": rowItemHeight + "px",
"width": _that.options.width + "px",
"class": (key == 2) ? "top-3-row-item-noborder" : "top-3-row-item"
});
dataDiv.append(rowItemDiv);
});
}else{
var htmlStr = "<div style=\"height: 100%; width: 100%; display: inline-table;\">" +
"<div class=\"" + _that.options.nameStyleClass + "\" style=\"text-align:center;\">No data to display</div>";
htmlStr += "</div>";
dataDiv.append(htmlStr);
}
return dataDiv;
},
setData: function (data) {
this.options.data = data;
var dataDiv = this._createDataDiv();
var footerDiv = this.element.find($("." + this.options.footerStyleClass));
this.element.find($(".top-three-kpi-data")).remove();
this.element.find($("." + this.options.footerStyleClass)).remove();
this.element.find($("." + this.options.containerStyleClass)).append(dataDiv).append(footerDiv);
},
getData: function () {
return this.options.data;
}
});
}(jQuery));