update Ox.Chart
This commit is contained in:
parent
511c355223
commit
c5af338d2d
4 changed files with 178 additions and 37 deletions
|
@ -76,7 +76,7 @@ Ox.load.Geo = function(options, callback) {
|
||||||
@*/
|
@*/
|
||||||
|
|
||||||
Ox.COUNTRIES = data;
|
Ox.COUNTRIES = data;
|
||||||
var colors = {
|
Ox.GEO_COLORS = {
|
||||||
|
|
||||||
'North America': [0, 0, 255],
|
'North America': [0, 0, 255],
|
||||||
'Northern America': [0, 0, 255],
|
'Northern America': [0, 0, 255],
|
||||||
|
@ -217,7 +217,7 @@ Ox.load.Geo = function(options, callback) {
|
||||||
};
|
};
|
||||||
|
|
||||||
Ox.getGeoColor = function(str) {
|
Ox.getGeoColor = function(str) {
|
||||||
return colors[str] || [128, 128, 128];
|
return Ox.GEO_COLORS[str] || [128, 128, 128];
|
||||||
};
|
};
|
||||||
|
|
||||||
callback(true);
|
callback(true);
|
||||||
|
|
|
@ -1,5 +1,24 @@
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
|
/*@
|
||||||
|
Ox.Chart <f> Bar Chart
|
||||||
|
() -> <o> Chart object
|
||||||
|
(options) -> <o> Chart object
|
||||||
|
(options, self) -> <o> Chart object
|
||||||
|
options <o> Options
|
||||||
|
color <[n]|[[n]]|[128, 128, 128]> Bar color
|
||||||
|
data <o> {k: v, ...} or {k: {k: v, ...}, ...}
|
||||||
|
formatKey <f|null> Format function for keys
|
||||||
|
keyAlign <s|'right'> Alignment of keys
|
||||||
|
keyWidth <n|128> Width of keys
|
||||||
|
rows <n|1> undocumented
|
||||||
|
sort <o|{key: 'value', operator: '-'}> Sort
|
||||||
|
title <s|''> Chart title
|
||||||
|
width <n|512> Chart width
|
||||||
|
self <o> shared private variable
|
||||||
|
|
||||||
|
@*/
|
||||||
|
|
||||||
Ox.Chart = function(options, self) {
|
Ox.Chart = function(options, self) {
|
||||||
|
|
||||||
self = self || {};
|
self = self || {};
|
||||||
|
@ -12,6 +31,7 @@ Ox.Chart = function(options, self) {
|
||||||
keyWidth: 128,
|
keyWidth: 128,
|
||||||
rows: 1,
|
rows: 1,
|
||||||
sort: {key: 'value', operator: '-'},
|
sort: {key: 'value', operator: '-'},
|
||||||
|
sortKey: null,
|
||||||
title: '',
|
title: '',
|
||||||
width: 512
|
width: 512
|
||||||
})
|
})
|
||||||
|
@ -23,33 +43,76 @@ Ox.Chart = function(options, self) {
|
||||||
overflowY: 'hidden'
|
overflowY: 'hidden'
|
||||||
});
|
});
|
||||||
|
|
||||||
|
self.valueWidth = self.options.width - self.options.keyWidth;
|
||||||
|
|
||||||
|
self.keys = Object.keys(self.options.data);
|
||||||
|
if (Ox.isObject(self.options.data[self.keys[0]])) {
|
||||||
|
if (Ox.isUndefined(options.color)) {
|
||||||
|
self.options.color = [
|
||||||
|
[192, 64, 64], [ 64, 192, 64], [ 64, 64, 192],
|
||||||
|
[192, 192, 64], [ 64, 192, 192], [192, 64, 192],
|
||||||
|
[192, 128, 64], [ 64, 192, 128], [128, 64, 192],
|
||||||
|
[192, 64, 128], [128, 192, 64], [ 64, 128, 192]
|
||||||
|
];
|
||||||
|
}
|
||||||
|
self.subData = {};
|
||||||
|
}
|
||||||
|
|
||||||
self.sort = {};
|
self.sort = {};
|
||||||
|
self.totals = {};
|
||||||
Ox.forEach(self.options.data, function(value, key) {
|
Ox.forEach(self.options.data, function(value, key) {
|
||||||
|
self.totals[key] = self.subData ? Ox.sum(value) : value;
|
||||||
|
if (self.subData) {
|
||||||
|
Object.keys(value).forEach(function(subKey) {
|
||||||
|
self.subData[subKey] = (self.subData[subKey] || 0) + value[subKey];
|
||||||
|
});
|
||||||
|
}
|
||||||
self.sort[key] = key.replace(/(\d+)/g, function(number) {
|
self.sort[key] = key.replace(/(\d+)/g, function(number) {
|
||||||
return Ox.pad(number, 16);
|
return Ox.pad(number, 16);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
self.max = Ox.max(self.totals);
|
||||||
|
self.sum = Ox.sum(self.totals);
|
||||||
|
|
||||||
|
if (self.subData) {
|
||||||
|
Ox.forEach(self.subData, function(subValue, subKey) {
|
||||||
|
self.sort[subKey] = subKey.replace(/(\d+)/g, function(number) {
|
||||||
|
return Ox.pad(number, 16);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
self.subKeys = Object.keys(self.subData).sort(function(a, b) {
|
||||||
|
var aValue = self.subData[a],
|
||||||
|
bValue = self.subData[b];
|
||||||
|
return a == '' ? 1
|
||||||
|
: b == '' ? -1
|
||||||
|
//: aValue < bValue ? 1
|
||||||
|
//: aValue > bValue ? -1
|
||||||
|
: self.sort[a] < self.sort[b] ? -1
|
||||||
|
: self.sort[a] > self.sort[b] ? 1
|
||||||
|
: 0;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
self.keys = Object.keys(self.options.data);
|
|
||||||
self.items = self.keys.map(function(key) {
|
self.items = self.keys.map(function(key) {
|
||||||
return {key: key, value: self.options.data[key]};
|
return {key: key, value: self.options.data[key]};
|
||||||
})
|
})
|
||||||
.sort(function(a, b) {
|
.sort(function(a, b) {
|
||||||
var key = self.options.sort.key,
|
var key = self.options.sort.key,
|
||||||
aValue = key == 'key' ? self.sort[a.key] : a.value,
|
aValue = key == 'key' ? self.sort[a.key]
|
||||||
bValue = key == 'key' ? self.sort[b.key] : b.value;
|
: self.subData ? self.totals[a.key] : a.value,
|
||||||
|
bValue = key == 'key' ? self.sort[b.key]
|
||||||
|
: self.subData ? self.totals[b.key] : b.value;
|
||||||
return aValue < bValue ? (self.options.sort.operator == '+' ? -1 : 1)
|
return aValue < bValue ? (self.options.sort.operator == '+' ? -1 : 1)
|
||||||
: aValue > bValue ? (self.options.sort.operator == '+' ? 1 : -1)
|
: aValue > bValue ? (self.options.sort.operator == '+' ? 1 : -1)
|
||||||
: self.sort[a.key] < self.sort[b.key] ? -1
|
: key == 'value' && self.sort[a.key] < self.sort[b.key] ? -1
|
||||||
: self.sort[a.key] > self.sort[b.key] ? 1
|
: key == 'value' && self.sort[a.key] > self.sort[b.key] ? 1
|
||||||
: 0;
|
: 0;
|
||||||
});
|
});
|
||||||
self.values = self.items.map(function(item) {
|
|
||||||
return item.value;
|
if (self.options.rows == 2) {
|
||||||
});
|
self.row = 0;
|
||||||
self.max = Ox.max(self.values);
|
}
|
||||||
self.sum = Ox.sum(self.values);
|
|
||||||
self.valueWidth = self.options.width - self.options.keyWidth;
|
|
||||||
self.$title = Ox.Bar({size: 16})
|
self.$title = Ox.Bar({size: 16})
|
||||||
.append(
|
.append(
|
||||||
$('<div>')
|
$('<div>')
|
||||||
|
@ -57,6 +120,7 @@ Ox.Chart = function(options, self) {
|
||||||
.html(self.options.title)
|
.html(self.options.title)
|
||||||
)
|
)
|
||||||
.appendTo(that);
|
.appendTo(that);
|
||||||
|
|
||||||
self.$chart = $('<div>')
|
self.$chart = $('<div>')
|
||||||
.css({position: 'absolute', top: '16px'})
|
.css({position: 'absolute', top: '16px'})
|
||||||
.append(renderChart())
|
.append(renderChart())
|
||||||
|
@ -80,6 +144,24 @@ Ox.Chart = function(options, self) {
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function getWidths(values) {
|
||||||
|
var max, maxKeys,
|
||||||
|
total = Ox.sum(values),
|
||||||
|
totalWidth = Math.round(total / self.max * self.valueWidth),
|
||||||
|
widths = {};
|
||||||
|
Ox.forEach(values, function(value, key) {
|
||||||
|
widths[key] = Math.round(value / total * totalWidth);
|
||||||
|
});
|
||||||
|
while (Ox.sum(widths) != totalWidth) {
|
||||||
|
max = Ox.max(widths);
|
||||||
|
maxKeys = Ox.map(Object.keys(widths), function(key) {
|
||||||
|
return widths[key] == max ? key : null;
|
||||||
|
});
|
||||||
|
widths[maxKeys[0]] += Ox.sum(widths) < totalWidth ? 1 : -1;
|
||||||
|
}
|
||||||
|
return widths;
|
||||||
|
}
|
||||||
|
|
||||||
function renderChart() {
|
function renderChart() {
|
||||||
return Ox.TextList({
|
return Ox.TextList({
|
||||||
columns: getColumns(),
|
columns: getColumns(),
|
||||||
|
@ -99,30 +181,88 @@ Ox.Chart = function(options, self) {
|
||||||
}
|
}
|
||||||
|
|
||||||
function renderValue(value, data) {
|
function renderValue(value, data) {
|
||||||
var color = Ox.isFunction(self.options.color)
|
var $bars = [],
|
||||||
? self.options.color(data.key)
|
$element,
|
||||||
: self.options.color,
|
colors = [], len, widths;
|
||||||
$element = Ox.Element({
|
if (!self.subData) {
|
||||||
element: '<div>',
|
$element = $bars[0] = Ox.Element({
|
||||||
tooltip: Ox.formatNumber(value)
|
element: '<div>',
|
||||||
+ ' (' + Ox.formatPercent(value * self.options.rows, self.sum, 2) + ')'
|
tooltip: Ox.formatNumber(value)
|
||||||
})
|
+ ' (' + Ox.formatPercent(value * self.options.rows, self.sum, 2) + ')'
|
||||||
.css({
|
})
|
||||||
width: Math.round(value / self.max * self.valueWidth) + 'px',
|
.css({
|
||||||
height: '14px',
|
width: Math.round(value / self.max * self.valueWidth) + 'px',
|
||||||
borderRadius: '4px',
|
height: '14px',
|
||||||
marginLeft: '-4px',
|
borderRadius: '4px',
|
||||||
|
marginLeft: '-4px'
|
||||||
|
});
|
||||||
|
colors[0] = Ox.isFunction(self.options.color)
|
||||||
|
? self.options.color(data.key) : self.options.color;
|
||||||
|
} else {
|
||||||
|
$element = $('<div>')
|
||||||
|
.css({
|
||||||
|
width: Math.round(self.totals[data.key] / self.max * self.valueWidth) + 'px',
|
||||||
|
height: '14px',
|
||||||
|
marginLeft: '-4px'
|
||||||
|
});
|
||||||
|
len = Ox.len(value);
|
||||||
|
widths = getWidths(value);
|
||||||
|
self.subKeys.forEach(function(subKey, subKeyIndex) {
|
||||||
|
var i = $bars.length,
|
||||||
|
subValue = value[subKey];
|
||||||
|
if (subValue) {
|
||||||
|
$bars[i] = Ox.Element({
|
||||||
|
element: '<div>',
|
||||||
|
/*
|
||||||
|
tooltip: Ox.formatNumber(self.totals[data.key])
|
||||||
|
+ ' (' + Ox.formatPercent(self.totals[data.key] * self.options.rows, self.sum, 2) + ')'
|
||||||
|
+ '<br>' + subKey + ': ' + Ox.formatNumber(subValue)
|
||||||
|
+ ' (' + Ox.formatPercent(subValue, self.totals[data.key], 2) + ')'
|
||||||
|
*/
|
||||||
|
tooltip: Ox.formatNumber(self.totals[data.key])
|
||||||
|
+ ' (' + Ox.formatPercent(self.totals[data.key] * self.options.rows, self.sum, 2) + ')'
|
||||||
|
})
|
||||||
|
.css({
|
||||||
|
float: 'left',
|
||||||
|
width: widths[subKey] + 'px',
|
||||||
|
height: '14px',
|
||||||
|
borderTopLeftRadius: i == 0 ? '4px' : 0,
|
||||||
|
borderBottomLeftRadius: i == 0 ? '4px' : 0,
|
||||||
|
borderTopRightRadius: i == len - 1 ? '4px' : 0,
|
||||||
|
borderBottomRightRadius: i == len - 1 ? '4px' : 0
|
||||||
|
})
|
||||||
|
.appendTo($element);
|
||||||
|
colors[i] = subKey == '' ? [128, 128, 128]
|
||||||
|
: Ox.isArray(self.options.color)
|
||||||
|
? self.options.color[subKeyIndex % self.options.color.length]
|
||||||
|
: Ox.isObject(self.options.color)
|
||||||
|
? self.options.color[subKey]
|
||||||
|
: self.options.color(subKey);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
['moz', 'o', 'webkit'].forEach(function(browser) {
|
}
|
||||||
$element.css({
|
$bars.forEach(function($bar, i) {
|
||||||
backgroundImage: '-' + browser
|
/*
|
||||||
+ '-linear-gradient(top, rgb(' + color.map(function(v) {
|
if (self.options.rows == 2) {
|
||||||
return Ox.limit(v + 16, 0, 255);
|
colors[i] = colors[i].map(function(v) {
|
||||||
}).join(', ') + '), rgb(' + color.map(function(v) {
|
return v + (self.row % 2 == 0 ? 16 : -16);
|
||||||
return Ox.limit(v - 16, 0, 255);
|
});
|
||||||
}) + '))'
|
}
|
||||||
|
*/
|
||||||
|
['moz', 'o', 'webkit'].forEach(function(browser) {
|
||||||
|
$bar.css({
|
||||||
|
backgroundImage: '-' + browser
|
||||||
|
+ '-linear-gradient(top, rgb(' + colors[i].map(function(v) {
|
||||||
|
return Ox.limit(v + 16, 0, 255);
|
||||||
|
}).join(', ') + '), rgb(' + colors[i].map(function(v) {
|
||||||
|
return Ox.limit(v - 16, 0, 255);
|
||||||
|
}) + '))'
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
if (self.options.rows == 2) {
|
||||||
|
self.row++;
|
||||||
|
}
|
||||||
return $element;
|
return $element;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -4,9 +4,9 @@
|
||||||
|
|
||||||
/*@
|
/*@
|
||||||
Ox.VideoEditor <f:Ox.Element> VideoEditor Object
|
Ox.VideoEditor <f:Ox.Element> VideoEditor Object
|
||||||
() -> <f> VideoEditor Object
|
() -> <o> VideoEditor Object
|
||||||
(options) -> <f> VideoEditor Object
|
(options) -> <o> VideoEditor Object
|
||||||
(options, self) -> <f> VideoEditor Object
|
(options, self) -> <o> VideoEditor Object
|
||||||
options <o> Options object
|
options <o> Options object
|
||||||
self <o> shared private variable
|
self <o> shared private variable
|
||||||
@*/
|
@*/
|
||||||
|
|
|
@ -72,6 +72,7 @@ Ox.VideoPlayer <f> Generic Video Player
|
||||||
({resolution: url, ...} or {resolution: [part1, part2, ...], ...})
|
({resolution: url, ...} or {resolution: [part1, part2, ...], ...})
|
||||||
volume <n|1> Volume (0-1)
|
volume <n|1> Volume (0-1)
|
||||||
width <n|256> Width in px
|
width <n|256> Width in px
|
||||||
|
self <o> shared private variable
|
||||||
@*/
|
@*/
|
||||||
|
|
||||||
Ox.VideoPlayer = function(options, self) {
|
Ox.VideoPlayer = function(options, self) {
|
||||||
|
|
Loading…
Add table
Reference in a new issue