Veronika
9 years ago
16 changed files with 1355 additions and 0 deletions
-
4web_graph_radar/README.md
-
0web_graph_radar/__init__.py
-
35web_graph_radar/__openerp__.py
-
39web_graph_radar/i18n/ar.po
-
39web_graph_radar/i18n/de.po
-
38web_graph_radar/i18n/en.po
-
39web_graph_radar/i18n/es.po
-
39web_graph_radar/i18n/fi.po
-
39web_graph_radar/i18n/pt_BR.po
-
39web_graph_radar/i18n/sl.po
-
39web_graph_radar/i18n/tr.po
-
BINweb_graph_radar/static/description/icon.png
-
885web_graph_radar/static/lib/nvd3-radar.js
-
86web_graph_radar/static/src/js/web_graph_radar.js
-
14web_graph_radar/static/src/xml/web_graph_radar.xml
-
20web_graph_radar/view/web_graph_radar.xml
@ -0,0 +1,4 @@ |
|||
Graph Radar Chart. |
|||
================= |
|||
|
|||
Add new graph view mode: Radar |
@ -0,0 +1,35 @@ |
|||
# -*- coding: utf-8 -*- |
|||
############################################################################## |
|||
# |
|||
# Author: Veronika Kotovich @ IT-PROJECTS |
|||
# Copyright (C) 2016 Veronika Kotovich <veronika.kotovich@gmail.com> |
|||
# |
|||
# This program is free software: you can redistribute it and/or modify |
|||
# it under the terms of the GNU Affero General Public License as |
|||
# published by the Free Software Foundation, either version 3 of the |
|||
# License, or (at your option) any later version. |
|||
# |
|||
# This program is distributed in the hope that it will be useful, |
|||
# but WITHOUT ANY WARRANTY; without even the implied warranty of |
|||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|||
# GNU Affero General Public License for more details. |
|||
# |
|||
# You should have received a copy of the GNU Affero General Public License |
|||
# along with this program. If not, see <http://www.gnu.org/licenses/>. |
|||
# |
|||
############################################################################## |
|||
|
|||
{ |
|||
'name': 'Radar Chart', |
|||
'version': '8.0.0.1.0', |
|||
'category': 'Web', |
|||
'summary': 'Add graph radar view.', |
|||
'author': "Veronika Kotovich,Odoo Community Association (OCA)", |
|||
'license': 'AGPL-3', |
|||
'website': 'https://twitter.com/vkotovi4', |
|||
'depends': ['web_graph'], |
|||
'qweb': ['static/src/xml/web_graph_radar.xml'], |
|||
'data': ['view/web_graph_radar.xml'], |
|||
'installable': True, |
|||
'auto_install': False, |
|||
} |
@ -0,0 +1,39 @@ |
|||
# Translation of Odoo Server. |
|||
# This file contains the translation of the following modules: |
|||
# * web_graph_improved |
|||
# |
|||
# Translators: |
|||
# SaFi J. <safi2266@gmail.com>, 2015 |
|||
msgid "" |
|||
msgstr "" |
|||
"Project-Id-Version: web (8.0)\n" |
|||
"Report-Msgid-Bugs-To: \n" |
|||
"POT-Creation-Date: 2015-12-16 07:41+0000\n" |
|||
"PO-Revision-Date: 2015-12-16 17:31+0000\n" |
|||
"Last-Translator: SaFi J. <safi2266@gmail.com>\n" |
|||
"Language-Team: Arabic (http://www.transifex.com/oca/OCA-web-8-0/language/ar/)\n" |
|||
"MIME-Version: 1.0\n" |
|||
"Content-Type: text/plain; charset=UTF-8\n" |
|||
"Content-Transfer-Encoding: \n" |
|||
"Language: ar\n" |
|||
"Plural-Forms: nplurals=6; plural=n==0 ? 0 : n==1 ? 1 : n==2 ? 2 : n%100>=3 && n%100<=10 ? 3 : n%100>=11 && n%100<=99 ? 4 : 5;\n" |
|||
|
|||
#. module: web_graph_improved |
|||
#. openerp-web |
|||
#: code:addons/web_graph_improved/static/src/js/web_graph_improved.js:13 |
|||
#: code:addons/web_graph_improved/static/src/js/web_graph_improved.js:14 |
|||
#, python-format |
|||
msgid "Total" |
|||
msgstr "المجموع الاجمالي" |
|||
|
|||
#. module: web_graph_improved |
|||
#. openerp-web |
|||
#: code:addons/web_graph_improved/static/src/js/web_graph_improved.js:30 |
|||
#: code:addons/web_graph_improved/static/src/js/web_graph_improved.js:40 |
|||
#: code:addons/web_graph_improved/static/src/js/web_graph_improved.js:44 |
|||
#: code:addons/web_graph_improved/static/src/js/web_graph_improved.js:49 |
|||
#: code:addons/web_graph_improved/static/src/js/web_graph_improved.js:54 |
|||
#: code:addons/web_graph_improved/static/src/js/web_graph_improved.js:57 |
|||
#, python-format |
|||
msgid "Undefined" |
|||
msgstr "غير معرف" |
@ -0,0 +1,39 @@ |
|||
# Translation of Odoo Server. |
|||
# This file contains the translation of the following modules: |
|||
# * web_graph_improved |
|||
# |
|||
# Translators: |
|||
# Rudolf Schnapka <rs@techno-flex.de>, 2016 |
|||
msgid "" |
|||
msgstr "" |
|||
"Project-Id-Version: web (8.0)\n" |
|||
"Report-Msgid-Bugs-To: \n" |
|||
"POT-Creation-Date: 2016-01-10 07:31+0000\n" |
|||
"PO-Revision-Date: 2016-01-18 20:15+0000\n" |
|||
"Last-Translator: Rudolf Schnapka <rs@techno-flex.de>\n" |
|||
"Language-Team: German (http://www.transifex.com/oca/OCA-web-8-0/language/de/)\n" |
|||
"MIME-Version: 1.0\n" |
|||
"Content-Type: text/plain; charset=UTF-8\n" |
|||
"Content-Transfer-Encoding: \n" |
|||
"Language: de\n" |
|||
"Plural-Forms: nplurals=2; plural=(n != 1);\n" |
|||
|
|||
#. module: web_graph_improved |
|||
#. openerp-web |
|||
#: code:addons/web_graph_improved/static/src/js/web_graph_improved.js:13 |
|||
#: code:addons/web_graph_improved/static/src/js/web_graph_improved.js:14 |
|||
#, python-format |
|||
msgid "Total" |
|||
msgstr "Gesamt" |
|||
|
|||
#. module: web_graph_improved |
|||
#. openerp-web |
|||
#: code:addons/web_graph_improved/static/src/js/web_graph_improved.js:30 |
|||
#: code:addons/web_graph_improved/static/src/js/web_graph_improved.js:40 |
|||
#: code:addons/web_graph_improved/static/src/js/web_graph_improved.js:44 |
|||
#: code:addons/web_graph_improved/static/src/js/web_graph_improved.js:49 |
|||
#: code:addons/web_graph_improved/static/src/js/web_graph_improved.js:54 |
|||
#: code:addons/web_graph_improved/static/src/js/web_graph_improved.js:57 |
|||
#, python-format |
|||
msgid "Undefined" |
|||
msgstr "Undefiniert" |
@ -0,0 +1,38 @@ |
|||
# Translation of Odoo Server. |
|||
# This file contains the translation of the following modules: |
|||
# * web_graph_improved |
|||
# |
|||
# Translators: |
|||
msgid "" |
|||
msgstr "" |
|||
"Project-Id-Version: web (8.0)\n" |
|||
"Report-Msgid-Bugs-To: \n" |
|||
"POT-Creation-Date: 2015-11-23 13:46+0000\n" |
|||
"PO-Revision-Date: 2015-11-07 11:20+0000\n" |
|||
"Last-Translator: OCA Transbot <transbot@odoo-community.org>\n" |
|||
"Language-Team: English (http://www.transifex.com/oca/OCA-web-8-0/language/en/)\n" |
|||
"MIME-Version: 1.0\n" |
|||
"Content-Type: text/plain; charset=UTF-8\n" |
|||
"Content-Transfer-Encoding: \n" |
|||
"Language: en\n" |
|||
"Plural-Forms: nplurals=2; plural=(n != 1);\n" |
|||
|
|||
#. module: web_graph_improved |
|||
#. openerp-web |
|||
#: code:addons/web_graph_improved/static/src/js/web_graph_improved.js:13 |
|||
#: code:addons/web_graph_improved/static/src/js/web_graph_improved.js:14 |
|||
#, python-format |
|||
msgid "Total" |
|||
msgstr "Total" |
|||
|
|||
#. module: web_graph_improved |
|||
#. openerp-web |
|||
#: code:addons/web_graph_improved/static/src/js/web_graph_improved.js:30 |
|||
#: code:addons/web_graph_improved/static/src/js/web_graph_improved.js:40 |
|||
#: code:addons/web_graph_improved/static/src/js/web_graph_improved.js:44 |
|||
#: code:addons/web_graph_improved/static/src/js/web_graph_improved.js:49 |
|||
#: code:addons/web_graph_improved/static/src/js/web_graph_improved.js:54 |
|||
#: code:addons/web_graph_improved/static/src/js/web_graph_improved.js:57 |
|||
#, python-format |
|||
msgid "Undefined" |
|||
msgstr "Undefined" |
@ -0,0 +1,39 @@ |
|||
# Translation of Odoo Server. |
|||
# This file contains the translation of the following modules: |
|||
# * web_graph_improved |
|||
# |
|||
# Translators: |
|||
# Pedro M. Baeza <pedro.baeza@gmail.com>, 2015 |
|||
msgid "" |
|||
msgstr "" |
|||
"Project-Id-Version: web (8.0)\n" |
|||
"Report-Msgid-Bugs-To: \n" |
|||
"POT-Creation-Date: 2015-11-23 13:46+0000\n" |
|||
"PO-Revision-Date: 2015-11-07 11:27+0000\n" |
|||
"Last-Translator: Pedro M. Baeza <pedro.baeza@gmail.com>\n" |
|||
"Language-Team: Spanish (http://www.transifex.com/oca/OCA-web-8-0/language/es/)\n" |
|||
"MIME-Version: 1.0\n" |
|||
"Content-Type: text/plain; charset=UTF-8\n" |
|||
"Content-Transfer-Encoding: \n" |
|||
"Language: es\n" |
|||
"Plural-Forms: nplurals=2; plural=(n != 1);\n" |
|||
|
|||
#. module: web_graph_improved |
|||
#. openerp-web |
|||
#: code:addons/web_graph_improved/static/src/js/web_graph_improved.js:13 |
|||
#: code:addons/web_graph_improved/static/src/js/web_graph_improved.js:14 |
|||
#, python-format |
|||
msgid "Total" |
|||
msgstr "Total" |
|||
|
|||
#. module: web_graph_improved |
|||
#. openerp-web |
|||
#: code:addons/web_graph_improved/static/src/js/web_graph_improved.js:30 |
|||
#: code:addons/web_graph_improved/static/src/js/web_graph_improved.js:40 |
|||
#: code:addons/web_graph_improved/static/src/js/web_graph_improved.js:44 |
|||
#: code:addons/web_graph_improved/static/src/js/web_graph_improved.js:49 |
|||
#: code:addons/web_graph_improved/static/src/js/web_graph_improved.js:54 |
|||
#: code:addons/web_graph_improved/static/src/js/web_graph_improved.js:57 |
|||
#, python-format |
|||
msgid "Undefined" |
|||
msgstr "Sin definir" |
@ -0,0 +1,39 @@ |
|||
# Translation of Odoo Server. |
|||
# This file contains the translation of the following modules: |
|||
# * web_graph_improved |
|||
# |
|||
# Translators: |
|||
# Jarmo Kortetjärvi <jarmo.kortetjarvi@gmail.com>, 2016 |
|||
msgid "" |
|||
msgstr "" |
|||
"Project-Id-Version: web (8.0)\n" |
|||
"Report-Msgid-Bugs-To: \n" |
|||
"POT-Creation-Date: 2016-01-10 07:31+0000\n" |
|||
"PO-Revision-Date: 2016-02-01 09:54+0000\n" |
|||
"Last-Translator: Jarmo Kortetjärvi <jarmo.kortetjarvi@gmail.com>\n" |
|||
"Language-Team: Finnish (http://www.transifex.com/oca/OCA-web-8-0/language/fi/)\n" |
|||
"MIME-Version: 1.0\n" |
|||
"Content-Type: text/plain; charset=UTF-8\n" |
|||
"Content-Transfer-Encoding: \n" |
|||
"Language: fi\n" |
|||
"Plural-Forms: nplurals=2; plural=(n != 1);\n" |
|||
|
|||
#. module: web_graph_improved |
|||
#. openerp-web |
|||
#: code:addons/web_graph_improved/static/src/js/web_graph_improved.js:13 |
|||
#: code:addons/web_graph_improved/static/src/js/web_graph_improved.js:14 |
|||
#, python-format |
|||
msgid "Total" |
|||
msgstr "Yhteensä" |
|||
|
|||
#. module: web_graph_improved |
|||
#. openerp-web |
|||
#: code:addons/web_graph_improved/static/src/js/web_graph_improved.js:30 |
|||
#: code:addons/web_graph_improved/static/src/js/web_graph_improved.js:40 |
|||
#: code:addons/web_graph_improved/static/src/js/web_graph_improved.js:44 |
|||
#: code:addons/web_graph_improved/static/src/js/web_graph_improved.js:49 |
|||
#: code:addons/web_graph_improved/static/src/js/web_graph_improved.js:54 |
|||
#: code:addons/web_graph_improved/static/src/js/web_graph_improved.js:57 |
|||
#, python-format |
|||
msgid "Undefined" |
|||
msgstr "Ei määritelty" |
@ -0,0 +1,39 @@ |
|||
# Translation of Odoo Server. |
|||
# This file contains the translation of the following modules: |
|||
# * web_graph_improved |
|||
# |
|||
# Translators: |
|||
# danimaribeiro <danimaribeiro@gmail.com>, 2016 |
|||
msgid "" |
|||
msgstr "" |
|||
"Project-Id-Version: web (8.0)\n" |
|||
"Report-Msgid-Bugs-To: \n" |
|||
"POT-Creation-Date: 2016-03-11 02:17+0000\n" |
|||
"PO-Revision-Date: 2016-03-05 16:20+0000\n" |
|||
"Last-Translator: danimaribeiro <danimaribeiro@gmail.com>\n" |
|||
"Language-Team: Portuguese (Brazil) (http://www.transifex.com/oca/OCA-web-8-0/language/pt_BR/)\n" |
|||
"MIME-Version: 1.0\n" |
|||
"Content-Type: text/plain; charset=UTF-8\n" |
|||
"Content-Transfer-Encoding: \n" |
|||
"Language: pt_BR\n" |
|||
"Plural-Forms: nplurals=2; plural=(n > 1);\n" |
|||
|
|||
#. module: web_graph_improved |
|||
#. openerp-web |
|||
#: code:addons/web_graph_improved/static/src/js/web_graph_improved.js:13 |
|||
#: code:addons/web_graph_improved/static/src/js/web_graph_improved.js:14 |
|||
#, python-format |
|||
msgid "Total" |
|||
msgstr "Total" |
|||
|
|||
#. module: web_graph_improved |
|||
#. openerp-web |
|||
#: code:addons/web_graph_improved/static/src/js/web_graph_improved.js:30 |
|||
#: code:addons/web_graph_improved/static/src/js/web_graph_improved.js:40 |
|||
#: code:addons/web_graph_improved/static/src/js/web_graph_improved.js:44 |
|||
#: code:addons/web_graph_improved/static/src/js/web_graph_improved.js:49 |
|||
#: code:addons/web_graph_improved/static/src/js/web_graph_improved.js:54 |
|||
#: code:addons/web_graph_improved/static/src/js/web_graph_improved.js:57 |
|||
#, python-format |
|||
msgid "Undefined" |
|||
msgstr "Não definido" |
@ -0,0 +1,39 @@ |
|||
# Translation of Odoo Server. |
|||
# This file contains the translation of the following modules: |
|||
# * web_graph_improved |
|||
# |
|||
# Translators: |
|||
# Matjaž Mozetič <m.mozetic@matmoz.si>, 2015 |
|||
msgid "" |
|||
msgstr "" |
|||
"Project-Id-Version: web (8.0)\n" |
|||
"Report-Msgid-Bugs-To: \n" |
|||
"POT-Creation-Date: 2015-11-23 13:46+0000\n" |
|||
"PO-Revision-Date: 2015-11-08 05:45+0000\n" |
|||
"Last-Translator: Matjaž Mozetič <m.mozetic@matmoz.si>\n" |
|||
"Language-Team: Slovenian (http://www.transifex.com/oca/OCA-web-8-0/language/sl/)\n" |
|||
"MIME-Version: 1.0\n" |
|||
"Content-Type: text/plain; charset=UTF-8\n" |
|||
"Content-Transfer-Encoding: \n" |
|||
"Language: sl\n" |
|||
"Plural-Forms: nplurals=4; plural=(n%100==1 ? 0 : n%100==2 ? 1 : n%100==3 || n%100==4 ? 2 : 3);\n" |
|||
|
|||
#. module: web_graph_improved |
|||
#. openerp-web |
|||
#: code:addons/web_graph_improved/static/src/js/web_graph_improved.js:13 |
|||
#: code:addons/web_graph_improved/static/src/js/web_graph_improved.js:14 |
|||
#, python-format |
|||
msgid "Total" |
|||
msgstr "Skupaj" |
|||
|
|||
#. module: web_graph_improved |
|||
#. openerp-web |
|||
#: code:addons/web_graph_improved/static/src/js/web_graph_improved.js:30 |
|||
#: code:addons/web_graph_improved/static/src/js/web_graph_improved.js:40 |
|||
#: code:addons/web_graph_improved/static/src/js/web_graph_improved.js:44 |
|||
#: code:addons/web_graph_improved/static/src/js/web_graph_improved.js:49 |
|||
#: code:addons/web_graph_improved/static/src/js/web_graph_improved.js:54 |
|||
#: code:addons/web_graph_improved/static/src/js/web_graph_improved.js:57 |
|||
#, python-format |
|||
msgid "Undefined" |
|||
msgstr "Nedoločeno" |
@ -0,0 +1,39 @@ |
|||
# Translation of Odoo Server. |
|||
# This file contains the translation of the following modules: |
|||
# * web_graph_improved |
|||
# |
|||
# Translators: |
|||
# Ahmet Altınışık <aaltinisik@altinkaya.com.tr>, 2015 |
|||
msgid "" |
|||
msgstr "" |
|||
"Project-Id-Version: web (8.0)\n" |
|||
"Report-Msgid-Bugs-To: \n" |
|||
"POT-Creation-Date: 2016-01-08 21:34+0000\n" |
|||
"PO-Revision-Date: 2015-12-30 22:16+0000\n" |
|||
"Last-Translator: Ahmet Altınışık <aaltinisik@altinkaya.com.tr>\n" |
|||
"Language-Team: Turkish (http://www.transifex.com/oca/OCA-web-8-0/language/tr/)\n" |
|||
"MIME-Version: 1.0\n" |
|||
"Content-Type: text/plain; charset=UTF-8\n" |
|||
"Content-Transfer-Encoding: \n" |
|||
"Language: tr\n" |
|||
"Plural-Forms: nplurals=2; plural=(n > 1);\n" |
|||
|
|||
#. module: web_graph_improved |
|||
#. openerp-web |
|||
#: code:addons/web_graph_improved/static/src/js/web_graph_improved.js:13 |
|||
#: code:addons/web_graph_improved/static/src/js/web_graph_improved.js:14 |
|||
#, python-format |
|||
msgid "Total" |
|||
msgstr "Toplam" |
|||
|
|||
#. module: web_graph_improved |
|||
#. openerp-web |
|||
#: code:addons/web_graph_improved/static/src/js/web_graph_improved.js:30 |
|||
#: code:addons/web_graph_improved/static/src/js/web_graph_improved.js:40 |
|||
#: code:addons/web_graph_improved/static/src/js/web_graph_improved.js:44 |
|||
#: code:addons/web_graph_improved/static/src/js/web_graph_improved.js:49 |
|||
#: code:addons/web_graph_improved/static/src/js/web_graph_improved.js:54 |
|||
#: code:addons/web_graph_improved/static/src/js/web_graph_improved.js:57 |
|||
#, python-format |
|||
msgid "Undefined" |
|||
msgstr "Tanımsız" |
After Width: 128 | Height: 128 | Size: 9.2 KiB |
@ -0,0 +1,885 @@ |
|||
nv.models.radar = function() { |
|||
|
|||
//============================================================
|
|||
// Public Variables with Default Settings
|
|||
//------------------------------------------------------------
|
|||
|
|||
var margin = {top: 0, right: 0, bottom: 0, left: 0} |
|||
, width = 500 |
|||
, height = 500 |
|||
, color = nv.utils.defaultColor() // a function that returns a color
|
|||
, getValue = function(d) { return d.value } // accessor to get the x value from a data point
|
|||
, size = 5 |
|||
, scales = d3.scale.linear() |
|||
, radius |
|||
, max = 5 |
|||
, startAngle = 0 |
|||
, cursor = 0 |
|||
, clipEdge = false |
|||
; |
|||
|
|||
var line = d3.svg.line() |
|||
.x(function(d) { return d.x}) |
|||
.y(function(d) { return d.y}); |
|||
|
|||
var scatter = nv.models.scatter() |
|||
.size(16) // default size
|
|||
.sizeDomain([16,256]) |
|||
; |
|||
|
|||
//============================================================
|
|||
|
|||
|
|||
//============================================================
|
|||
// Private Variables
|
|||
//------------------------------------------------------------
|
|||
|
|||
|
|||
//============================================================
|
|||
|
|||
|
|||
function chart(selection) { |
|||
selection.each(function(data) { |
|||
|
|||
var availableWidth = width - margin.left - margin.right, |
|||
availableHeight = height - margin.top - margin.bottom, |
|||
container = d3.select(this) |
|||
; |
|||
|
|||
// max = max || d3.max(data, getValue) > 0 ? d3.max(data, getValue) : 1
|
|||
|
|||
scales.domain([0, max]).range([0,radius]); |
|||
|
|||
var current = 0; |
|||
if (cursor < 0) { |
|||
current = Math.abs(cursor); |
|||
} |
|||
else if (cursor > 0) { |
|||
current = size - cursor; |
|||
} |
|||
|
|||
|
|||
//------------------------------------------------------------
|
|||
// Setup Scales
|
|||
//compute proportions
|
|||
var maxValue = 0; |
|||
for(var i=0; i<data.length; i++) { |
|||
var serie = data[i].values; |
|||
for(var j=0; j<serie.length; j++) { |
|||
if (serie[j].value > maxValue) { |
|||
maxValue = serie[j].value; |
|||
} |
|||
} |
|||
} |
|||
var factor = maxValue ? (radius-40)/maxValue/max/2 : 0; |
|||
data = data.map(function(serie, i) { |
|||
serie.values = serie.values.map(function(value, j) { |
|||
value.x = calculateX(value.value*factor, j, size); |
|||
value.y = calculateY(value.value*factor, j, size); |
|||
value.serie = i; |
|||
value.focus = (current == j) ? true : false; |
|||
return value; |
|||
}); |
|||
return serie; |
|||
}); |
|||
|
|||
//------------------------------------------------------------
|
|||
|
|||
|
|||
|
|||
//------------------------------------------------------------
|
|||
// Setup containers and skeleton of chart
|
|||
|
|||
var wrap = container.selectAll('g.nv-wrap.nv-radar').data([data]); |
|||
var wrapEnter = wrap.enter().append('g').attr('class', 'nvd3 nv-wrap nv-radar'); |
|||
var defsEnter = wrapEnter.append('defs'); |
|||
var gEnter = wrapEnter.append('g'); |
|||
var g = wrap.select('g') |
|||
|
|||
gEnter.append('g').attr('class', 'nv-groups'); |
|||
gEnter.append('g').attr('class', 'nv-scatterWrap'); |
|||
|
|||
|
|||
// wrap.attr('transform', 'translate(' + radius + ',' + radius + ')');
|
|||
|
|||
//------------------------------------------------------------
|
|||
|
|||
// Points
|
|||
scatter |
|||
.xScale(scales) |
|||
.yScale(scales) |
|||
.zScale(scales) |
|||
.color(color) |
|||
.useVoronoi(false) |
|||
.width(availableWidth) |
|||
.height(availableHeight); |
|||
|
|||
var scatterWrap = wrap.select('.nv-scatterWrap'); |
|||
//.datum(data); // Data automatically trickles down from the wrap
|
|||
|
|||
d3.transition(scatterWrap).call(scatter); |
|||
|
|||
defsEnter.append('clipPath') |
|||
.attr('id', 'nv-edge-clip-' + scatter.id()) |
|||
.append('rect'); |
|||
|
|||
wrap.select('#nv-edge-clip-' + scatter.id() + ' rect') |
|||
.attr('width', availableWidth) |
|||
.attr('height', availableHeight); |
|||
|
|||
g.attr('clip-path', clipEdge ? 'url(#nv-edge-clip-' + scatter.id() + ')' : ''); |
|||
scatterWrap |
|||
.attr('clip-path', clipEdge ? 'url(#nv-edge-clip-' + scatter.id() + ')' : ''); |
|||
|
|||
|
|||
// Series
|
|||
var groups = wrap.select('.nv-groups').selectAll('.nv-group').data(function(d) { return d }, function(d) { return d.key }); |
|||
groups.enter().append('g') |
|||
.style('stroke-opacity', 1e-6) |
|||
.style('fill-opacity', 1e-6); |
|||
d3.transition(groups.exit()) |
|||
.style('stroke-opacity', 1e-6) |
|||
.style('fill-opacity', 1e-6) |
|||
.remove(); |
|||
groups |
|||
.attr('class', function(d,i) { return 'nv-group nv-series-' + i }) |
|||
.style('fill', function(d,i){ return color(d,i); }) |
|||
.style('stroke', function(d,i){ return color(d,i); }); |
|||
d3.transition(groups) |
|||
.style('stroke-opacity', 1) |
|||
.style('fill-opacity', .5); |
|||
|
|||
var lineRadar = groups.selectAll('path.nv-line').data(function(d) { return [d.values] }); |
|||
|
|||
lineRadar.enter().append('path') |
|||
.attr('class', 'nv-line') |
|||
.attr('d', line ); |
|||
|
|||
|
|||
d3.transition(lineRadar.exit()) |
|||
.attr('d', line) |
|||
.remove(); |
|||
|
|||
lineRadar |
|||
.style('fill', function(d){ return color(d,d[0].serie); }) |
|||
.style('stroke', function(d,i,j){ return color(d,d[0].serie); }) |
|||
|
|||
d3.transition(lineRadar) |
|||
.attr('d', line ); |
|||
|
|||
|
|||
|
|||
}); |
|||
|
|||
return chart; |
|||
} |
|||
|
|||
// compute an angle
|
|||
function angle(i, length) { |
|||
return i * (2 * Math.PI / length ) + ((2 * Math.PI) * startAngle / 360) + (cursor*2*Math.PI)/length; |
|||
} |
|||
|
|||
// x-caclulator
|
|||
// d is the datapoint, i is the index, length is the length of the data
|
|||
function calculateX(d, i, length) { |
|||
var l = scales(d); |
|||
return Math.sin(angle(i, length)) * l; |
|||
} |
|||
|
|||
// y-calculator
|
|||
function calculateY(d, i, length) { |
|||
var l = scales(d); |
|||
return Math.cos(angle(i, length)) * l; |
|||
} |
|||
|
|||
|
|||
//============================================================
|
|||
// Expose Public Variables
|
|||
//------------------------------------------------------------
|
|||
|
|||
chart.dispatch = scatter.dispatch; |
|||
chart.scatter = scatter; |
|||
|
|||
chart.margin = function(_) { |
|||
if (!arguments.length) return margin; |
|||
margin.top = typeof _.top != 'undefined' ? _.top : margin.top; |
|||
margin.right = typeof _.right != 'undefined' ? _.right : margin.right; |
|||
margin.bottom = typeof _.bottom != 'undefined' ? _.bottom : margin.bottom; |
|||
margin.left = typeof _.left != 'undefined' ? _.left : margin.left; |
|||
return chart; |
|||
}; |
|||
|
|||
chart.width = function(_) { |
|||
if (!arguments.length) return width; |
|||
width = _; |
|||
return chart; |
|||
}; |
|||
|
|||
chart.height = function(_) { |
|||
if (!arguments.length) return height; |
|||
height = _; |
|||
return chart; |
|||
}; |
|||
|
|||
chart.size = function(_) { |
|||
if (!arguments.length) return size; |
|||
size = _; |
|||
return chart; |
|||
}; |
|||
|
|||
chart.scales = function(_) { |
|||
if (!arguments.length) return scales; |
|||
scales = _; |
|||
return chart; |
|||
}; |
|||
|
|||
chart.max = function(_) { |
|||
if (!arguments.length) return max; |
|||
max = _; |
|||
return chart; |
|||
}; |
|||
|
|||
chart.radius = function(_) { |
|||
if (!arguments.length) return radius; |
|||
radius = _; |
|||
return chart; |
|||
}; |
|||
|
|||
chart.color = function(_) { |
|||
if (!arguments.length) return color; |
|||
color = nv.utils.getColor(_); |
|||
return chart; |
|||
}; |
|||
|
|||
chart.startAngle = function(_) { |
|||
if (!arguments.length) return startAngle; |
|||
startAngle = _; |
|||
return chart; |
|||
}; |
|||
|
|||
chart.cursor = function(_) { |
|||
if (!arguments.length) return cursor; |
|||
cursor = _; |
|||
return chart; |
|||
}; |
|||
|
|||
//============================================================
|
|||
|
|||
|
|||
return chart; |
|||
} |
|||
|
|||
nv.models.radarChart = function() { |
|||
|
|||
//============================================================
|
|||
// Public Variables with Default Settings
|
|||
//------------------------------------------------------------
|
|||
|
|||
var radars = nv.models.radar() |
|||
, legend = nv.models.legend(); |
|||
|
|||
var margin = {top: 0, right: 0, bottom: 0, left: 0} |
|||
, color = nv.utils.defaultColor() |
|||
, width = null |
|||
, height = null |
|||
, showLegend = true |
|||
, legs = [] |
|||
, ticks = 10 //Temp to test radar size issue
|
|||
, scales = d3.scale.linear() |
|||
, edit = false |
|||
, radius |
|||
, startAngle = 180 |
|||
, cursor = 0 |
|||
, tooltips = true |
|||
, transitionDuration = 250 |
|||
, tooltip = function(key, leg, value, e, graph) { |
|||
return '<h3>' + key + '</h3>' + |
|||
'<p>' + leg + ': ' + value + '</p>' |
|||
} |
|||
, dispatch = d3.dispatch('tooltipShow', 'tooltipHide','prevClick','stateChange') |
|||
; |
|||
|
|||
var line = d3.svg.line() |
|||
.x(function(d) { return d.x}) |
|||
.y(function(d) { return d.y}); |
|||
|
|||
//============================================================
|
|||
|
|||
|
|||
//============================================================
|
|||
// Private Variables
|
|||
//------------------------------------------------------------
|
|||
|
|||
var showTooltip = function(e, offsetElement) { |
|||
|
|||
// New addition to calculate position if SVG is scaled with viewBox, may move TODO: consider implementing everywhere else
|
|||
if (offsetElement) { |
|||
var svg = d3.select(offsetElement).select('svg'); |
|||
var viewBox = svg.attr('viewBox'); |
|||
if (viewBox) { |
|||
viewBox = viewBox.split(' '); |
|||
var ratio = parseInt(svg.style('width')) / viewBox[2]; |
|||
e.pos[0] = e.pos[0] * ratio; |
|||
e.pos[1] = e.pos[1] * ratio; |
|||
} |
|||
} |
|||
|
|||
var left = e.pos[0] + ( offsetElement.offsetLeft || 0 ), |
|||
top = e.pos[1] + ( offsetElement.offsetTop || 0), |
|||
val = e.series.values[e.pointIndex].value, |
|||
leg = legs[e.pointIndex].label, |
|||
content = tooltip(e.series.key, leg, val, e, chart); |
|||
nv.tooltip.show([left, top], content, null, null, offsetElement); |
|||
}; |
|||
|
|||
//============================================================
|
|||
|
|||
|
|||
function chart(selection) { |
|||
selection.each(function(data) { |
|||
legs=data[0].values;//TODO: Think in a better way to put only the legs of the radar
|
|||
var container = d3.select(this), |
|||
that = this, |
|||
size = legs.length, |
|||
availableWidth = (width || parseInt(container.style('width')) || 500) - margin.left - margin.right, |
|||
availableHeight = (height || parseInt(container.style('height')) || 500) - margin.top - margin.bottom; |
|||
|
|||
chart.update = function() { container.transition().duration(transitionDuration).call(chart) }; |
|||
chart.container = this; |
|||
|
|||
var current = 0; |
|||
if (cursor < 0) { |
|||
current = Math.abs(cursor); |
|||
} |
|||
else if (cursor > 0) { |
|||
current = legs.length - cursor; |
|||
} |
|||
|
|||
//------------------------------------------------------------
|
|||
// Setup Scales
|
|||
|
|||
// scales = radars.scales();
|
|||
radius = (availableWidth-300 >= availableHeight) ? (availableHeight)/2 : (availableWidth-300)/2; |
|||
scales.domain([0, ticks]).range([0,radius]); |
|||
|
|||
//------------------------------------------------------------
|
|||
|
|||
//------------------------------------------------------------
|
|||
// Setup containers and skeleton of chart
|
|||
|
|||
var wrap = container.selectAll('g.nv-wrap.nv-radarChart').data([data]); |
|||
var wrapEnter = wrap.enter().append('g').attr('class', 'nvd3 nv-wrap nv-radarChart'); |
|||
var gEnter = wrapEnter.append('g'); |
|||
var g = wrap.select('g'); |
|||
|
|||
gEnter.append('g').attr('class', 'nv-controlWrap'); |
|||
gEnter.append('g').attr('class', 'nv-gridWrap'); |
|||
gEnter.append('g').attr('class', 'nv-radarsWrap'); |
|||
gEnter.append('g').attr('class', 'nv-legendWrap'); |
|||
|
|||
var gridWrap = wrap.select('g.nv-gridWrap'); |
|||
gridWrap.append("g").attr("class", "grid"); |
|||
gridWrap.append("g").attr("class", "axes"); |
|||
|
|||
wrap.attr('transform', 'translate(' + parseFloat(radius + margin.left) + ',' + parseFloat(radius + margin.top) + ')'); |
|||
|
|||
//------------------------------------------------------------
|
|||
|
|||
|
|||
//------------------------------------------------------------
|
|||
// Legend
|
|||
|
|||
if (showLegend) { |
|||
legend.width(30); |
|||
|
|||
g.select('.nv-legendWrap') |
|||
.datum(data) |
|||
.call(legend); |
|||
|
|||
/* |
|||
if ( margin.top != legend.height()) { |
|||
margin.top = legend.height(); |
|||
availableHeight = (height || parseInt(container.style('height')) || 400) |
|||
- margin.top - margin.bottom; |
|||
} |
|||
*/ |
|||
g.select('.nv-legendWrap') |
|||
.attr('transform', 'translate(' + (radius + margin.left + margin.right) + ',' + (-radius) +')'); |
|||
} |
|||
|
|||
//------------------------------------------------------------
|
|||
|
|||
if (edit) { |
|||
startAngle = 135 |
|||
//Focus
|
|||
var currentLeg = legs[current]; |
|||
var rgbLeg = hexToRgb("#000000"); |
|||
var controlWrap = wrap.select('g.nv-controlWrap'); |
|||
|
|||
wrap.select('g.control').remove(); |
|||
var controlEnter = controlWrap.append("g") |
|||
.attr("class", "control"); |
|||
|
|||
var controlLine = controlEnter.append("svg:line") |
|||
.attr('class', 'indicator') |
|||
.style("stroke", "#000000") |
|||
.style("fill", "none") |
|||
.style("opacity", 1) |
|||
.style("stroke-width", 1.5) |
|||
.attr("x1", Math.sin(angle(current, size)) * scales(scales.domain()[1])) |
|||
.attr("y1", Math.cos(angle(current, size)) * scales(scales.domain()[1])) |
|||
.attr("x2", Math.sin(angle(current, size)) * scales(scales.domain()[1])) |
|||
.attr("y2", Math.cos(angle(current, size)) * scales(scales.domain()[1])); |
|||
|
|||
var controlDescription = controlEnter.append("svg:foreignObject") |
|||
.attr('width',200) |
|||
.attr('height',0) |
|||
.attr("x", Math.sin(angle(current, size)) * scales(scales.domain()[1]) * 2) |
|||
.attr("y", Math.cos(angle(current, size)) * scales(scales.domain()[1])); |
|||
|
|||
controlDescription.append("xhtml:div") |
|||
.attr('class', 'radar-description') |
|||
.style("background-color", 'rgba('+rgbLeg.r+','+rgbLeg.g+','+rgbLeg.b+',0.1)') |
|||
.style('border-bottom', '1px solid '+"#000000") |
|||
.style("padding", "10px") |
|||
.style("text-align", "justify") |
|||
.text( currentLeg.description ); |
|||
|
|||
|
|||
var controlActionContent = controlEnter.append("svg:foreignObject") |
|||
.attr('width',200) |
|||
.attr('height',50) |
|||
.attr("x", Math.sin(angle(current, size)) * scales(scales.domain()[1]) * 2) |
|||
.attr("y", Math.cos(angle(current, size)) * scales(scales.domain()[1]) - 25); |
|||
|
|||
controlActionContent.append("xhtml:button") |
|||
.attr('type','button') |
|||
.attr('class','radar-prev btn btn-mini icon-arrow-left') |
|||
.text('prev'); |
|||
|
|||
|
|||
var controlSelect = controlActionContent.append("xhtml:select") |
|||
.attr('class','radar-select-note'); |
|||
|
|||
controlSelect.append('xhtml:option') |
|||
.attr('value',0) |
|||
// .attr('selected', function(d,i){ return (d[0].values[current].value == 0) ? true : false;})
|
|||
.text('Note') |
|||
controlSelect.append('xhtml:option') |
|||
.attr('value',1) |
|||
// .attr('selected', function(d,i){ return (d[0].values[current].value == 1) ? true : false;})
|
|||
.text('Nul') |
|||
controlSelect.append('xhtml:option') |
|||
.attr('value',2) |
|||
//.attr('selected', function(d,i){ return (d[0].values[current].value == 2) ? true : false;})
|
|||
.text('Mauvais') |
|||
controlSelect.append('xhtml:option') |
|||
.attr('value',3) |
|||
// .attr('selected', function(d,i){ return (d[0].values[current].value == 3) ? true : false;})
|
|||
.text('Nul') |
|||
controlSelect.append('xhtml:option') |
|||
.attr('value',4) |
|||
// .attr('selected', function(d,i){ return (d[0].values[current].value == 4) ? true : false;})
|
|||
.text('Bien') |
|||
controlSelect.append('xhtml:option') |
|||
.attr('value',5) |
|||
// .attr('selected', function(d,i){ return (d[0].values[current].value == 4) ? true : false;})
|
|||
.text('Très bien') |
|||
|
|||
controlActionContent.append("xhtml:button") |
|||
.attr('type','button') |
|||
.attr('class','radar-next btn btn-mini icon-arrow-right') |
|||
.text('next'); |
|||
|
|||
|
|||
var checkOption = function (d) { |
|||
if(d[0].values[current].value == this.value){ |
|||
return d3.select(this).attr("selected", "selected"); |
|||
} |
|||
}; |
|||
|
|||
controlSelect.selectAll("option").each(checkOption); |
|||
|
|||
// Animation
|
|||
controlLine.transition().duration(500) |
|||
.attr("x1", Math.sin(angle(current, size)) * scales(scales.domain()[1])) |
|||
.attr("y1", Math.cos(angle(current, size)) * scales(scales.domain()[1])) |
|||
.attr("x2", Math.sin(angle(current, size)) * scales(scales.domain()[1]) * 2 + 200) |
|||
.attr("y2", Math.cos(angle(current, size)) * scales(scales.domain()[1])) |
|||
.each('end', function(d){ controlDescription.transition().duration(300).attr('height','100%') }); |
|||
|
|||
// Controls
|
|||
controlWrap.select('.radar-prev') |
|||
.on('click', function(d) { |
|||
chart.prev(); |
|||
selection.transition().call(chart); |
|||
}); |
|||
controlWrap.select('.radar-next') |
|||
.on('click', function(d) { |
|||
chart.next(); |
|||
selection.transition().call(chart); |
|||
}); |
|||
|
|||
controlWrap.select('.radar-select-note') |
|||
.on('change', function(d) { |
|||
d[0].values[current].value = this.value; |
|||
chart.next(); |
|||
selection.transition().call(chart); |
|||
}); |
|||
|
|||
//change
|
|||
} else { |
|||
cursor = 0; |
|||
startAngle = 180; |
|||
wrap.select('g.control').remove(); |
|||
} |
|||
|
|||
//------------------------------------------------------------
|
|||
// Main Chart Component(s)
|
|||
|
|||
radars |
|||
.width(availableWidth) |
|||
.height(availableHeight) |
|||
.size(legs.length) |
|||
.max(ticks) |
|||
.startAngle(startAngle) |
|||
.cursor(cursor) |
|||
// .scales(scales)
|
|||
.radius(radius) |
|||
.color(data.map(function(d,i) { |
|||
return d.color || color(d, i); |
|||
}).filter(function(d,i) { return !data[i].disabled })) |
|||
; |
|||
|
|||
|
|||
var radarWrap = g.select('.nv-radarsWrap') |
|||
.datum(data.filter(function(d) { return !d.disabled })); |
|||
|
|||
d3.transition(radarWrap).call(radars); |
|||
|
|||
//------------------------------------------------------------
|
|||
|
|||
//------------------------------------------------------------
|
|||
// Setup Axes
|
|||
|
|||
// the grid data, number of ticks
|
|||
var gridData = buildAxisGrid(size, ticks); |
|||
|
|||
// Grid
|
|||
var grid = wrap.select('.grid').selectAll('.gridlevel').data(gridData); |
|||
grid.exit().remove(); |
|||
|
|||
grid.enter().append("path") |
|||
.attr("class", "gridlevel") |
|||
.attr("d", line); |
|||
|
|||
|
|||
d3.transition(grid) |
|||
.attr('d', line ); |
|||
|
|||
grid.style("stroke", "#000") |
|||
.style("fill", "none") |
|||
.style("opacity", 0.3); |
|||
|
|||
// Axes
|
|||
var ax = wrap.select("g.axes").selectAll("g.axis").data(legs); |
|||
ax.exit().remove(); |
|||
|
|||
var axEnter = ax.enter().append("g") |
|||
.attr("class", "axis"); |
|||
|
|||
var legText = axEnter.append("svg:text") |
|||
.style("text-anchor", function(d, i) { |
|||
var x = Math.sin(angle(i, size)) * scales(scales.domain()[1]); |
|||
if (Math.abs(x) < 0.1) { |
|||
return "middle" |
|||
} |
|||
if (x > 0) { |
|||
return "start" |
|||
} |
|||
|
|||
return "end" |
|||
}) |
|||
.attr("dy", function(d, i) { |
|||
var y = Math.cos(angle(i, size)) * scales(scales.domain()[1]); |
|||
|
|||
if (Math.abs(y) < 0.1) { |
|||
return ".72em" |
|||
} |
|||
|
|||
if (y > 0) { |
|||
return "1em" |
|||
} |
|||
return "-.3em" |
|||
}) |
|||
.style("fill", function(d){ return d.color; }) |
|||
.style("font-size", "9pt") |
|||
.style("font-weight",function(d,i){ return (i == current && edit) ? "bold": "normal"; }) |
|||
.style("opacity", function(d,i){ return (i == current && edit) ? 1: 0.4; }) |
|||
.text(function(d){ return d.label}) |
|||
.attr("x", function(d, i) { return Math.sin(angle(i, size)) * scales(scales.domain()[1]);}) |
|||
.attr("y", function(d, i) { return Math.cos(angle(i, size)) * scales(scales.domain()[1]);}) |
|||
; |
|||
|
|||
legText.on('click', function(d,i) { |
|||
chart.cursor(legs.length - i); |
|||
selection.transition().call(chart); |
|||
}); |
|||
|
|||
d3.transition(ax) |
|||
.select("text") |
|||
.style("text-anchor", function(d, i) { |
|||
var x = Math.sin(angle(i, size)) * scales(scales.domain()[1]); |
|||
if (Math.abs(x) < 0.1) { |
|||
return "middle" |
|||
} |
|||
if (x > 0) { |
|||
return "start" |
|||
} |
|||
|
|||
return "end" |
|||
}) |
|||
.attr("dy", function(d, i) { |
|||
var y = Math.cos(angle(i, size)) * scales(scales.domain()[1]); |
|||
|
|||
if (Math.abs(y) < 0.1) { |
|||
return ".72em" |
|||
} |
|||
|
|||
if (y > 0) { |
|||
return "1em" |
|||
} |
|||
return "-.3em" |
|||
}) |
|||
.style("font-weight",function(d,i){ return (i == current && edit) ? "bold": "normal"; }) |
|||
.style("opacity", function(d,i){ return (i == current && edit) ? 1: 0.4; }) |
|||
.attr("x", function(d, i) { return Math.sin(angle(i, size)) * scales(scales.domain()[1]);}) |
|||
.attr("y", function(d, i) { return Math.cos(angle(i, size)) * scales(scales.domain()[1]);}); |
|||
|
|||
axEnter.append("svg:line") |
|||
.style("stroke", function(d){ return d.color; }) |
|||
.style("fill", "none") |
|||
.style("stroke-width", 2) |
|||
.style("opacity", function(d,i){ return (i == current && edit) ? 1: 0.4; }) |
|||
.attr("x1", function(d, i) { return Math.sin(angle(i, size)) * scales(scales.domain()[0]);}) |
|||
.attr("y1", function(d, i) { return Math.cos(angle(i, size)) * scales(scales.domain()[0]);}) |
|||
.attr("x2", function(d, i) { return Math.sin(angle(i, size)) * scales(scales.domain()[1]);}) |
|||
.attr("y2", function(d, i) { return Math.cos(angle(i, size)) * scales(scales.domain()[1]);}); |
|||
|
|||
d3.transition(ax) |
|||
.select("line") |
|||
.style("opacity", function(d,i){ return (i == current && edit) ? 1: 0.4; }) |
|||
.attr("x1", function(d, i) { return Math.sin(angle(i, size)) * scales(scales.domain()[0]);}) |
|||
.attr("y1", function(d, i) { return Math.cos(angle(i, size)) * scales(scales.domain()[0]);}) |
|||
.attr("x2", function(d, i) { return Math.sin(angle(i, size)) * scales(scales.domain()[1]);}) |
|||
.attr("y2", function(d, i) { return Math.cos(angle(i, size)) * scales(scales.domain()[1]);}); |
|||
//------------------------------------------------------------
|
|||
|
|||
//============================================================
|
|||
// Event Handling/Dispatching (in chart's scope)
|
|||
//------------------------------------------------------------
|
|||
|
|||
radars.dispatch.on('elementClick', function(d,i) { |
|||
chart.cursor(legs.length - d.pointIndex); |
|||
selection.transition().call(chart); |
|||
}); |
|||
legend.dispatch.on('stateChange', function(newState) { |
|||
state = newState; |
|||
dispatch.stateChange(state); |
|||
chart.update(); |
|||
}); |
|||
/*legend.dispatch.on('legendClick', function(d,i) { |
|||
if (!d.disabled) return; |
|||
data = data.map(function(s) { |
|||
s.disabled = true; |
|||
return s; |
|||
}); |
|||
d.disabled = false; |
|||
|
|||
switch (d.key) { |
|||
case 'Grouped': |
|||
multibar.stacked(false); |
|||
break; |
|||
case 'Stacked': |
|||
multibar.stacked(true); |
|||
break; |
|||
} |
|||
|
|||
state.stacked = multibar.stacked(); |
|||
dispatch.stateChange(state); |
|||
|
|||
chart.update(); |
|||
});*/ |
|||
|
|||
/* legend.dispatch.on('legendClick', function(d,i) { |
|||
d.disabled = !d.disabled; |
|||
|
|||
if (!data.filter(function(d) { return !d.disabled }).length) { |
|||
data.map(function(d) { |
|||
d.disabled = false; |
|||
wrap.selectAll('.nv-series').classed('disabled', false); |
|||
|
|||
return d; |
|||
}); |
|||
} |
|||
chart.update(); |
|||
});*/ |
|||
|
|||
dispatch.on('tooltipShow', function(e) { |
|||
e.pos = [parseFloat(e.pos[0] + availableHeight/2 + margin.left), parseFloat(e.pos[1] + availableHeight/2 + margin.top)]; |
|||
if (tooltips) showTooltip(e, that.parentNode); |
|||
}); |
|||
|
|||
//============================================================
|
|||
|
|||
}); |
|||
|
|||
return chart; |
|||
} |
|||
|
|||
function hexToRgb(hex,opacity) { |
|||
var result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex); |
|||
return result ? { |
|||
r: parseInt(result[1], 16), |
|||
g: parseInt(result[2], 16), |
|||
b: parseInt(result[3], 16) |
|||
} : null; |
|||
} |
|||
|
|||
function rgbToHex(r, g, b) { |
|||
return "#" + ((1 << 24) + (r << 16) + (g << 8) + b).toString(16).slice(1); |
|||
} |
|||
|
|||
// compute an angle
|
|||
function angle(i, length) { |
|||
return i * (2 * Math.PI / length ) + ((2 * Math.PI) * startAngle / 360) + (cursor*2*Math.PI)/length; |
|||
} |
|||
|
|||
// x-caclulator
|
|||
// d is the datapoint, i is the index, length is the length of the data
|
|||
function calculateX(d, i, length) { |
|||
var l = scales(d); |
|||
return Math.sin(angle(i, length)) * l; |
|||
} |
|||
|
|||
// y-calculator
|
|||
function calculateY(d, i, length) { |
|||
var l = scales(d); |
|||
return Math.cos(angle(i, length)) * l; |
|||
} |
|||
|
|||
// * build the spider axis * //
|
|||
// rewrite this to conform to d3 axis style? //
|
|||
function buildAxisGrid(length, ticks) { |
|||
var min = scales.domain()[0]; |
|||
var max = scales.domain()[1] > 0 ? scales.domain()[1] : 1; |
|||
var increase = max/ticks; |
|||
|
|||
var gridData = [] |
|||
for (var i = 0; i <= ticks; i++ ) { |
|||
var val = min + i*increase; |
|||
var d = [val]; |
|||
var gridPoints = []; |
|||
|
|||
for (var j = 0; j <= length; j++) { |
|||
gridPoints.push({ |
|||
x: calculateX(d, j, length), |
|||
y: calculateY(d, j, length), |
|||
}); |
|||
} |
|||
|
|||
gridData.push(gridPoints) |
|||
} |
|||
|
|||
return gridData; |
|||
} |
|||
|
|||
//============================================================
|
|||
// Event Handling/Dispatching (out of chart's scope)
|
|||
//------------------------------------------------------------
|
|||
|
|||
radars.dispatch.on('elementMouseover.tooltip', function(e) { |
|||
dispatch.tooltipShow(e); |
|||
}); |
|||
|
|||
radars.dispatch.on('elementMouseout.tooltip', function(e) { |
|||
dispatch.tooltipHide(e); |
|||
}); |
|||
|
|||
dispatch.on('tooltipHide', function() { |
|||
if (tooltips) nv.tooltip.cleanup(); |
|||
}); |
|||
|
|||
//============================================================
|
|||
|
|||
|
|||
//============================================================
|
|||
// Expose Public Variables
|
|||
//------------------------------------------------------------
|
|||
|
|||
// expose chart's sub-components
|
|||
chart.dispatch = dispatch; |
|||
chart.radars = radars; |
|||
|
|||
|
|||
chart.margin = function(_) { |
|||
if (!arguments.length) return margin; |
|||
margin.top = typeof _.top != 'undefined' ? _.top : margin.top; |
|||
margin.right = typeof _.right != 'undefined' ? _.right : margin.right; |
|||
margin.bottom = typeof _.bottom != 'undefined' ? _.bottom : margin.bottom; |
|||
margin.left = typeof _.left != 'undefined' ? _.left : margin.left; |
|||
return chart; |
|||
}; |
|||
|
|||
chart.width = function(_) { |
|||
if (!arguments.length) return width; |
|||
width = _; |
|||
return chart; |
|||
}; |
|||
|
|||
chart.height = function(_) { |
|||
if (!arguments.length) return height; |
|||
height = _; |
|||
return chart; |
|||
}; |
|||
|
|||
chart.legs = function(_) { |
|||
if (!arguments.length) return legs; |
|||
legs = _; |
|||
return chart; |
|||
}; |
|||
|
|||
chart.showLegend = function(_) { |
|||
if (!arguments.length) return showLegend; |
|||
showLegend = _; |
|||
return chart; |
|||
}; |
|||
|
|||
chart.cursor = function(_) { |
|||
if (!arguments.length) return cursor; |
|||
cursor = _; |
|||
return chart; |
|||
}; |
|||
|
|||
chart.next = function(_) { |
|||
cursor = cursor - 1; |
|||
if (Math.abs(cursor) > legs.length-1) cursor = 0; |
|||
return chart; |
|||
}; |
|||
|
|||
chart.prev = function(_) { |
|||
cursor = cursor + 1; |
|||
if (cursor > legs.length-1) cursor = 0; |
|||
return chart; |
|||
}; |
|||
|
|||
chart.edit = function(_) { |
|||
if (!arguments.length) return edit; |
|||
edit = _; |
|||
return chart; |
|||
}; |
|||
//============================================================
|
|||
|
|||
|
|||
return chart; |
|||
} |
@ -0,0 +1,86 @@ |
|||
openerp.web_graph_radar = function(instance) { |
|||
|
|||
var _t = instance.web._t; |
|||
|
|||
instance.web_graph.Graph.include({ |
|||
template: 'GraphWidgetRadar', |
|||
radar: function() { |
|||
var self = this, |
|||
dim_x = this.pivot.rows.groupby.length, |
|||
dim_y = this.pivot.cols.groupby.length, |
|||
data; |
|||
|
|||
// No groupby
|
|||
if ((dim_x === 0) && (dim_y === 0)) { |
|||
data = [{key: _t('Total'), values:[{ |
|||
label: _t('Total'), |
|||
value: this.pivot.get_total()[0], |
|||
}]}]; |
|||
// Only column groupbys
|
|||
} else if ((dim_x === 0) && (dim_y >= 1)){ |
|||
data = _.map(this.pivot.get_cols_with_depth(1), function (header) { |
|||
return { |
|||
key: header.title, |
|||
values: [{label:header.title, value: self.pivot.get_total(header)[0]}] |
|||
}; |
|||
}); |
|||
// Just 1 row groupby
|
|||
} else if ((dim_x === 1) && (dim_y === 0)) { |
|||
data = _.map(self.pivot.measures, function(measure, i) { |
|||
var series = _.map(self.pivot.main_row().children, function (pt) { |
|||
var value = self.pivot.get_total(pt)[i], |
|||
title = (pt.title !== undefined) ? pt.title : _t('Undefined'); |
|||
return {label: title, value: value}; |
|||
}); |
|||
return {key: self.pivot.measures[i].string, values:series}; |
|||
}); |
|||
// 1 row groupby and some col groupbys
|
|||
} else if ((dim_x === 1) && (dim_y >= 1)) { |
|||
data = _.map(this.pivot.get_cols_with_depth(1), function (colhdr) { |
|||
var values = _.map(self.pivot.get_rows_with_depth(1), function (header) { |
|||
return { |
|||
label: header.title || _t('Undefined'), |
|||
value: self.pivot.get_values(header.id, colhdr.id)[0] || 0 |
|||
}; |
|||
}); |
|||
return {key: colhdr.title || _t('Undefined'), values: values}; |
|||
}); |
|||
// At least two row groupby
|
|||
} else { |
|||
var keys = _.uniq(_.map(this.pivot.get_rows_with_depth(2), function (hdr) { |
|||
return hdr.title || _t('Undefined'); |
|||
})); |
|||
data = _.map(keys, function (key) { |
|||
var values = _.map(self.pivot.get_rows_with_depth(1), function (hdr) { |
|||
var subhdr = _.find(hdr.children, function (child) { |
|||
return ((child.title === key) || ((child.title === undefined) && (key === _t('Undefined')))); |
|||
}); |
|||
return { |
|||
label: hdr.title || _t('Undefined'), |
|||
value: (subhdr) ? self.pivot.get_total(subhdr)[0] : 0 |
|||
}; |
|||
}); |
|||
return {key:key, values: values}; |
|||
}); |
|||
} |
|||
console.log(data); |
|||
nv.addGraph(function () { |
|||
var chart = nv.models.radarChart(); |
|||
// .stacked(self.bar_ui === 'stack')
|
|||
// .showControls(show_controls);
|
|||
|
|||
chart.margin({left:200, top:20, bottom:20}); |
|||
|
|||
d3.select(self.svg) |
|||
.datum(data) |
|||
.attr('width', self.width) |
|||
.attr('height', self.height) |
|||
.call(chart); |
|||
|
|||
// nv.utils.windowResize(chart.update);
|
|||
return chart; |
|||
}); |
|||
|
|||
} |
|||
}); |
|||
} |
@ -0,0 +1,14 @@ |
|||
<?xml version="1.0" encoding="UTF-8"?> |
|||
<!-- vim:fdl=1: |
|||
--> |
|||
<templates id="template" xml:space="preserve"> |
|||
|
|||
<t t-name="GraphWidgetRadar" t-extend="GraphWidget"> |
|||
<t t-jquery=".graph_mode_selection" t-operation="append"> |
|||
<label class="btn btn-default" data-mode="radar" title="Radar Chart"> |
|||
<input type="radio" name="modes"/><span class="fa fa-certificate"></span> |
|||
</label> |
|||
</t> |
|||
</t> |
|||
|
|||
</templates> |
@ -0,0 +1,20 @@ |
|||
<?xml version="1.0" encoding="utf-8"?> |
|||
|
|||
<openerp> |
|||
<data> |
|||
|
|||
<template id="assets_backend" |
|||
name="web_graph_radar assets" |
|||
inherit_id="web.assets_backend"> |
|||
<xpath expr="." position="inside"> |
|||
<script type="text/javascript" |
|||
src="/web_graph_radar/static/lib/nvd3-radar.js"> |
|||
</script> |
|||
<script type="text/javascript" |
|||
src="/web_graph_radar/static/src/js/web_graph_radar.js"> |
|||
</script> |
|||
</xpath> |
|||
</template> |
|||
|
|||
</data> |
|||
</openerp> |
Write
Preview
Loading…
Cancel
Save
Reference in new issue