├── pentaho-plugin └── saiku-chart-plus │ ├── images │ └── chart.png │ ├── js │ └── google.js │ ├── version.xml │ ├── plugin.xml │ ├── LICENSES.txt │ ├── css │ └── plugin.css │ └── saiku │ └── plugins │ └── saiku-chart-plus.js ├── saiku-server └── saiku-chart-plus │ ├── images │ └── chart.png │ ├── js │ └── google.js │ ├── LICENSES.txt │ ├── css │ └── plugin.css │ └── plugin.js └── README.md /pentaho-plugin/saiku-chart-plus/images/chart.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/it4biz/SaikuChartPlus/HEAD/pentaho-plugin/saiku-chart-plus/images/chart.png -------------------------------------------------------------------------------- /saiku-server/saiku-chart-plus/images/chart.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/it4biz/SaikuChartPlus/HEAD/saiku-server/saiku-chart-plus/images/chart.png -------------------------------------------------------------------------------- /saiku-server/saiku-chart-plus/js/google.js: -------------------------------------------------------------------------------- 1 | setTimeout(function(){google.load('visualization', '1', {'callback':'', 'packages':['geochart','geomap']})}, 2000); -------------------------------------------------------------------------------- /pentaho-plugin/saiku-chart-plus/js/google.js: -------------------------------------------------------------------------------- 1 | setTimeout(function(){google.load('visualization', '1', {'callback':'', 'packages':['geochart','geomap']})}, 2000); -------------------------------------------------------------------------------- /pentaho-plugin/saiku-chart-plus/version.xml: -------------------------------------------------------------------------------- 1 | 2 | ChartPlusStable 3 | -------------------------------------------------------------------------------- /pentaho-plugin/saiku-chart-plus/plugin.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /pentaho-plugin/saiku-chart-plus/LICENSES.txt: -------------------------------------------------------------------------------- 1 | Licenses 2 | Before you put this project in your production environment, 3 | please visit http://www.highcharts.com/ to learn more about 4 | the Highchart project, and https://developers.google.com/maps/terms 5 | to learn more about the Google GeoChart project. 6 | 7 | Saiku Chart Plus is a free and open source software. The UI, contained 8 | in this repository, is available under the terms of the Apache License 9 | Version 2. A copy is attached for your convenience. -------------------------------------------------------------------------------- /saiku-server/saiku-chart-plus/LICENSES.txt: -------------------------------------------------------------------------------- 1 | Licenses 2 | Before you put this project in your production environment, 3 | please visit http://www.highcharts.com/ to learn more about 4 | the Highchart project, and https://developers.google.com/maps/terms 5 | to learn more about the Google GeoChart project. 6 | 7 | Saiku Chart Plus is a free and open source software. The UI, contained 8 | in this repository, is available under the terms of the Apache License 9 | Version 2. A copy is attached for your convenience. -------------------------------------------------------------------------------- /saiku-server/saiku-chart-plus/css/plugin.css: -------------------------------------------------------------------------------- 1 | #nav, #nav ul{ 2 | overflow: visible; 3 | z-index:100; 4 | margin:0; 5 | padding:0; 6 | list-style-type:none; 7 | list-style-position:outside; 8 | position:relative; 9 | line-height:1.5em; 10 | background: #fff; 11 | border-radius: 6px; 12 | box-shadow: 0 2px 8px rgba(0, 0, 0, 0.45); 13 | } 14 | 15 | #nav a{ 16 | display:relative; 17 | padding:0px 5px; 18 | color:#555555; 19 | text-decoration:none; 20 | } 21 | 22 | .menu{ 23 | border: 1px solid #D5D5D5; 24 | margin: 2px 2px; 25 | } 26 | 27 | .menu:hover{ 28 | background:#155FB0; 29 | color: #FFFFFF; 30 | text-decoration: none; 31 | box-shadow: 0 2px 8px rgba(0, 0, 0, 0); 32 | } 33 | 34 | .menu ul li:hover{ 35 | background:#155FB0; 36 | text-decoration: none; 37 | border-radius: 6px; 38 | box-shadow: 0 2px 8px rgba(0, 0, 0, 0.45); 39 | } 40 | 41 | .menu a:hover{ 42 | color:#FFFFFF !important; 43 | } 44 | 45 | #nav li{ 46 | float:left; 47 | position:relative; 48 | } 49 | 50 | #nav ul { 51 | position:absolute; 52 | display:none; 53 | width:13em; 54 | top:1.5em; 55 | } 56 | 57 | #nav li ul a{ 58 | width:12em; 59 | height:auto; 60 | float:left; 61 | } 62 | 63 | #nav ul ul{ 64 | top:auto; 65 | } 66 | 67 | #nav li ul ul { 68 | left:12em; 69 | margin:0px 0 0 10px; 70 | } 71 | 72 | #nav li:hover ul ul, #nav li:hover ul ul ul, #nav li:hover ul ul ul ul{ 73 | display:none; 74 | } 75 | #nav li:hover ul, #nav li li:hover ul, #nav li li li:hover ul, #nav li li li li:hover ul{ 76 | display:block; 77 | } 78 | 79 | #nav .submenu:after { 80 | content: ">"; 81 | color: #666; 82 | position: absolute; 83 | top: 0; 84 | right: 3px; 85 | z-index: 1; 86 | } 87 | -------------------------------------------------------------------------------- /pentaho-plugin/saiku-chart-plus/css/plugin.css: -------------------------------------------------------------------------------- 1 | #nav, #nav ul{ 2 | overflow: visible; 3 | z-index:100; 4 | margin:0; 5 | padding:0; 6 | list-style-type:none; 7 | list-style-position:outside; 8 | position:relative; 9 | line-height:1.5em; 10 | background: #fff; 11 | border-radius: 6px; 12 | box-shadow: 0 2px 8px rgba(0, 0, 0, 0.45); 13 | } 14 | 15 | #nav a{ 16 | display:relative; 17 | padding:0px 5px; 18 | color:#555555; 19 | text-decoration:none; 20 | } 21 | 22 | .menu{ 23 | border: 1px solid #D5D5D5; 24 | margin: 2px 2px; 25 | } 26 | 27 | .menu:hover{ 28 | background:#155FB0; 29 | color: #FFFFFF; 30 | text-decoration: none; 31 | box-shadow: 0 2px 8px rgba(0, 0, 0, 0); 32 | } 33 | 34 | .menu ul li:hover{ 35 | background:#155FB0; 36 | text-decoration: none; 37 | border-radius: 6px; 38 | box-shadow: 0 2px 8px rgba(0, 0, 0, 0.45); 39 | } 40 | 41 | .menu a:hover{ 42 | color:#FFFFFF !important; 43 | } 44 | 45 | #nav li{ 46 | float:left; 47 | position:relative; 48 | } 49 | 50 | #nav ul { 51 | position:absolute; 52 | display:none; 53 | width:13em; 54 | top:1.5em; 55 | } 56 | 57 | #nav li ul a{ 58 | width:12em; 59 | height:auto; 60 | float:left; 61 | } 62 | 63 | #nav ul ul{ 64 | top:auto; 65 | } 66 | 67 | #nav li ul ul { 68 | left:12em; 69 | margin:0px 0 0 10px; 70 | } 71 | 72 | #nav li:hover ul ul, #nav li:hover ul ul ul, #nav li:hover ul ul ul ul{ 73 | display:none; 74 | } 75 | #nav li:hover ul, #nav li li:hover ul, #nav li li li:hover ul, #nav li li li li:hover ul{ 76 | display:block; 77 | } 78 | 79 | #nav .submenu:after { 80 | content: ">"; 81 | color: #666; 82 | position: absolute; 83 | top: 0; 84 | right: 3px; 85 | z-index: 1; 86 | } 87 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Saiku Chart Plus 2 | 3 | Welcome to Saiku Chart Plus Project. 4 | 5 | What is Saiku Chart Plus? 6 | 7 | It is an open source project that helps Pentaho BI users to create other types of charts and maps based on Saiku Project, Highcharts and Google Maps. 8 | 9 | Saiku Chart Plus is used by more than 120 countries around the World. 10 | 11 | ### Read More 12 | 13 | To learn more visit our page http://it4biz.github.com/SaikuChartPlus/ 14 | 15 | 16 | ### Installation 17 | 18 | * For Pentaho BA Users, please use Pentaho Marketplace 19 | * For Saiku Server Users, please follow the tutorial at section "advanced instalation" in http://it4biz.github.io/SaikuChartPlus/ 20 | 21 | ### Support 22 | * If you need support please feel free to create a issue here https://github.com/it4biz/SaikuChartPlus/issues we will do our best to help you. 23 | 24 | ### Licenses 25 | 26 | Before you put this project in your production environment, please visit http://www.highcharts.com/ to learn more about the Highchart project, and https://developers.google.com/maps/terms to learn more about the Google GeoChart project. 27 | 28 | Saiku Chart Plus is a free and open source software. The UI, contained in this repository, is available under the terms of the Apache License Version 2. A copy is attached for your convenience. 29 | 30 | 31 | ###Changelog 32 | 33 | 3.1RC1 (on development...) 34 | * Add Interactive Heatmaps with Google Maps API v3 (https://github.com/it4biz/SaikuChartPlus/issues/35); 35 | * Work in open issues; 36 | 37 | 3.0 Stable version: 38 | * Ready to work with Saiku 3 39 | 40 | 2.4 Stable version: 41 | * Position legend - https://github.com/it4biz/SaikuChartPlus/issues/4 42 | * Error label description - https://github.com/it4biz/SaikuChartPlus/issues/11 43 | * Add support for multiple measures at geoChart/Map 44 | * Ass support to GeoChart with resolution provinces 45 | 46 | 2.5 RC4 version: 47 | * Removed dependency of bootstrap 48 | 49 | * Removed Highcharts Exporting file because insconsistence with IE 50 | 51 | * Changed Button Plus, add togle for table render button 52 | 53 | ###People talking about us 54 | http://www.osbi.fr/saiku-chart-plus/
55 | http://www.redopenbi.com/group/saiku/forum/topics/tutorial-01-saiku-chart-plus-geomap-y-geochart
56 | http://www.dataprix.com/blog-it/business-intelligence/saiku-chart-plus-geomap-geochart

57 | 58 | If your link is not listed, please contact us by email info@it4biz.com.br
59 | -------------------------------------------------------------------------------- /pentaho-plugin/saiku-chart-plus/saiku/plugins/saiku-chart-plus.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2014 IT4biz IT Solutions Ltda 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * changed by it4biz.com.br 16 | */ 17 | 18 | /** 19 | * Renders a chart for each workspace 20 | */ 21 | var ChartPlus = Backbone.View.extend({ 22 | 23 | initialize: function(args) { 24 | this.workspace = args.workspace; 25 | 26 | // Create a unique ID for use as the CSS selector 27 | this.id = _.uniqueId("chartPlus_"); 28 | $(this.el).attr({ id: this.id }); 29 | 30 | // Bind table rendering to query result event 31 | _.bindAll(this, "render", "receive_data", "process_data", "show", 32 | "setOptions"); 33 | 34 | this.workspace.bind('query:result', this.receive_data); 35 | 36 | // Add chart button 37 | this.add_button(); 38 | this.workspace.toolbar.chartPlus = this.show; 39 | 40 | // Listen to adjust event and rerender chart 41 | this.workspace.bind('workspace:adjust', this.render); 42 | 43 | // Create navigation 44 | this.nav = $("
"+ 45 | ""+ 627 | "
"); 628 | 629 | 630 | 631 | 632 | 633 | this.nav.find('a').click(this.setOptions); 634 | 635 | //function for menu 636 | $("#nav ul ").css({display: "none"}); // Opera Fix 637 | $("#nav li").hover(function(){ 638 | $(this).find('ul:first').css({visibility: "visible",display: "none"}).show(400); 639 | },function(){ 640 | $(this).find('ul:first').css({visibility: "hidden"}); 641 | }); 642 | 643 | // Append chart to workspace 644 | $(this.workspace.el).find('.workspace_results') 645 | .prepend($(this.el).hide()) 646 | .prepend(this.nav.hide()); 647 | 648 | 649 | 650 | }, 651 | 652 | add_button: function() { 653 | var $chart_button = 654 | $('') 655 | .css({ 'background-image': "url('../saiku-chart-plus/images/chart.png')", 656 | 'background-repeat':'no-repeat', 657 | 'background-position':'20% 50%' 658 | }); 659 | 660 | var $chart_li = $('
  • ').append($chart_button); 661 | $(this.workspace.toolbar.el).find("ul").append($chart_li); 662 | }, 663 | 664 | show: function(event, ui) { 665 | $(this.workspace.table.el).toggle(); 666 | $(this.el).toggle(); 667 | $(this.nav).toggle(); 668 | $(event.target).toggleClass('on'); 669 | 670 | if ($(event.target).hasClass('on')) { 671 | this.render(); 672 | } else { 673 | this.workspace.table.render({ data: this.workspace.query.result.lastresult() }); 674 | } 675 | }, 676 | 677 | setOptions: function(event) { 678 | var type = $(event.target).attr('href').replace('#', ''); 679 | var chartOptions=[]; 680 | chartOptions.type=type; 681 | 682 | try { 683 | if(type=='geoChart' || type=='geoMap'){ 684 | var region=$(event.target).attr('id'); 685 | chartOptions.region=region; 686 | this.render(chartOptions); 687 | }else 688 | this.render(chartOptions); 689 | } catch (e) { } 690 | 691 | return false; 692 | }, 693 | 694 | render: function(chartOptions) { 695 | 696 | if (! $(this.workspace.toolbar.el).find('.chartPlus').hasClass('on')) { 697 | return; 698 | } 699 | 700 | //configurações default 701 | var options = _.extend({ 702 | canvas: this.id, 703 | width: $(this.workspace.el).find('.workspace_results').width() - 40, 704 | height: $(this.workspace.el).find('.workspace_results').height() - 40, 705 | yAxisSize: 70, 706 | orientation: 'vertical', 707 | stacked: false, 708 | animate: false, 709 | showValues: false, 710 | legend: true, 711 | legendPosition:"top", 712 | legendAlign: "right", 713 | colors: ["#B40010", "#CCC8B4", "#DDB965", "#72839D", "#1D2D40"], 714 | serializeType: "highCharts", 715 | type: 'bar' 716 | }, chartOptions); 717 | 718 | //start serialization of data 719 | if(options.type!='pie' && options.type!='geoMap' && options.type!='geoChart'){ 720 | var metadata=new Array(); 721 | //numero de colunas 722 | var colNumberY=this.data.metadata.length-1;//-1 devido a coluna 0 armazena o valor de X 723 | var x=new Array(); 724 | var y=new Array(); 725 | for(var i=0; i < colNumberY; i++){ 726 | y[i]=new Array(); 727 | } 728 | 729 | 730 | if (this.data.resultset.length > 0 ) { 731 | $.each(this.data.resultset, function(key, value) { 732 | x[key]=value[0]; 733 | for(var i=0; i < colNumberY; i++){ 734 | y[i][key]=value[i+1];// +1 devido ao valor de x armazenado na coluna 0 735 | } 736 | 737 | }); 738 | } 739 | 740 | var seriesData=[]; 741 | for(var i=0; i < colNumberY; i++){ 742 | seriesData[i]={ 743 | name: this.data.metadata[i+1].colName, 744 | data: y[i] 745 | }; 746 | } 747 | }else if(options.type=='pie' && options.type!='geoMap' && options.type!='geoChart'){ 748 | if(this.data.metadata.length>0){ 749 | var metadata=new Array(); 750 | //numero de colunas 751 | var colNumber=this.data.metadata.length; 752 | var seriesData=new Array(); 753 | var series=new Array(); 754 | if (this.data.resultset.length > 0 ) { 755 | $.each(this.data.resultset, function(key, value) { 756 | series[key]=[value[0], value[1]]; 757 | }); 758 | } 759 | 760 | seriesData=[{ 761 | type: 'pie', 762 | name: this.data.metadata[0].colName, 763 | data: series 764 | }]; 765 | }else{ 766 | return false; 767 | } 768 | }else if(options.type=='geoMap'){ 769 | if(this.data.metadata.length>0){ 770 | var series=[]; 771 | //nome das colunas 772 | var column=[]; 773 | 774 | column[0]=this.data.metadata[0].colName; 775 | column[1]=this.data.metadata[1].colName; 776 | series[0]=column; 777 | 778 | 779 | if (this.data.resultset.length > 0 ) { 780 | var data= this.data; 781 | $.each(this.data.resultset, function(key, value) { 782 | var array=[]; 783 | array[0]=value[0]; 784 | array[1]=value[1]; 785 | array[2]=value[1]; 786 | for(var i=2; i < data.metadata.length; i++){ 787 | columnName=data.metadata[i].colName; 788 | value=value[i]; 789 | array[2]+=', '+columnName+': '+value; 790 | } 791 | series[key+1]=array; // +1 devido ao nome das colunas 792 | }); 793 | } 794 | 795 | }else{ 796 | return false; 797 | } 798 | 799 | }else{//options.type=='geoChart' 800 | var series=[]; 801 | //nome das colunas 802 | var column=[]; 803 | for(var i=0; i < this.data.metadata.length; i++) 804 | column[i]=this.data.metadata[i].colName; 805 | series[0]=column; 806 | 807 | if (this.data.resultset.length > 0 ) { 808 | $.each(this.data.resultset, function(key, value) { 809 | series[key+1]=value; // +1 devido ao nome das colunas 810 | }); 811 | } 812 | } 813 | //end serialization of data 814 | 815 | //start draw graphics 816 | if(options.type=='bar'){ 817 | chart = new Highcharts.Chart({ 818 | chart: { 819 | renderTo: this.id, 820 | type: 'bar', 821 | zoomType: 'x,y', 822 | height: $(this.workspace.el).find('.workspace_results').height() - 40, 823 | width: $(this.workspace.el).find('.workspace_results').width() - 40 824 | }, 825 | title: { 826 | text: '', 827 | x: -20 //center 828 | }, 829 | credits: { 830 | text: 'Saiku Chart Plus Plugin by IT4biz', 831 | href: 'http://it4biz.github.com/SaikuChartPlus' 832 | }, 833 | subtitle: { 834 | text: '', 835 | x: -20 836 | }, 837 | xAxis: { 838 | categories: x 839 | }, 840 | yAxis: { 841 | title: { 842 | text: '' 843 | }, 844 | plotLines: [{ 845 | value: 0, 846 | width: 1, 847 | color: '#808080' 848 | }] 849 | }, 850 | tooltip: { 851 | formatter: function() { 852 | return ''+ this.series.name +'
    '+ 853 | this.x +': '+ this.y +''; 854 | } 855 | }, 856 | legend: { 857 | layout: 'vertical', 858 | align: 'right', 859 | verticalAlign: 'top', 860 | x: -10, 861 | y: 100, 862 | borderWidth: 0 863 | }, 864 | series: seriesData 865 | }); 866 | } 867 | else if(options.type=='stackedBar') 868 | { 869 | chart = new Highcharts.Chart({ 870 | chart: { 871 | renderTo: this.id, 872 | type: 'bar', 873 | zoomType: 'x,y', 874 | height: $(this.workspace.el).find('.workspace_results').height() - 40, 875 | width: $(this.workspace.el).find('.workspace_results').width() - 40 876 | }, 877 | title: { 878 | text: '', 879 | x: -20 //center 880 | }, 881 | credits: { 882 | text: 'Saiku Chart Plus Plugin by IT4biz', 883 | href: 'http://it4biz.github.com/SaikuChartPlus' 884 | }, 885 | subtitle: { 886 | text: '', 887 | x: -20 888 | }, 889 | xAxis: { 890 | categories: x 891 | }, 892 | yAxis: { 893 | title: { 894 | text: '' 895 | }, 896 | plotLines: [{ 897 | value: 0, 898 | width: 1, 899 | color: '#808080' 900 | }] 901 | }, 902 | plotOptions: { 903 | series: { 904 | stacking: 'normal' 905 | } 906 | }, 907 | tooltip: { 908 | formatter: function() { 909 | return ''+ this.series.name +'
    '+ 910 | this.x +': '+ this.y +''; 911 | } 912 | }, 913 | legend: { 914 | layout: 'vertical', 915 | align: 'right', 916 | verticalAlign: 'top', 917 | x: -10, 918 | y: 100, 919 | borderWidth: 0 920 | }, 921 | series: seriesData 922 | }); 923 | } 924 | else if(options.type=='column') 925 | { 926 | chart = new Highcharts.Chart({ 927 | chart: { 928 | renderTo: this.id, 929 | type: 'column', 930 | zoomType: 'x,y', 931 | height: $(this.workspace.el).find('.workspace_results').height() - 40, 932 | width: $(this.workspace.el).find('.workspace_results').width() - 40 933 | }, 934 | credits: { 935 | text: 'Saiku Chart Plus Plugin by IT4biz', 936 | href: 'http://it4biz.github.com/SaikuChartPlus' 937 | }, 938 | title: { 939 | text: '', 940 | x: -20 //center 941 | }, 942 | subtitle: { 943 | text: '', 944 | x: -20 945 | }, 946 | xAxis: { 947 | categories: x, 948 | labels: { 949 | rotation: -90, 950 | align: 'right' 951 | } 952 | }, 953 | yAxis: { 954 | title: { 955 | text: '' 956 | }, 957 | plotLines: [{ 958 | value: 0, 959 | width: 1, 960 | color: '#808080' 961 | }] 962 | }, 963 | tooltip: { 964 | formatter: function() { 965 | return ''+ this.series.name +'
    '+ 966 | this.x +': '+ this.y +''; 967 | } 968 | }, 969 | legend: { 970 | layout: 'vertical', 971 | align: 'right', 972 | verticalAlign: 'top', 973 | x: -10, 974 | y: 100, 975 | borderWidth: 0 976 | }, 977 | series: seriesData 978 | }); 979 | } 980 | else if(options.type=='stackedColumn') 981 | { 982 | chart = new Highcharts.Chart({ 983 | chart: { 984 | renderTo: this.id, 985 | type: 'column', 986 | zoomType: 'x,y', 987 | height: $(this.workspace.el).find('.workspace_results').height() - 40, 988 | width: $(this.workspace.el).find('.workspace_results').width() - 40 989 | }, 990 | credits: { 991 | text: 'Saiku Chart Plus Plugin by IT4biz', 992 | href: 'http://it4biz.github.com/SaikuChartPlus' 993 | }, 994 | title: { 995 | text: '', 996 | x: -20 //center 997 | }, 998 | subtitle: { 999 | text: '', 1000 | x: -20 1001 | }, 1002 | xAxis: { 1003 | categories: x, 1004 | labels: { 1005 | rotation: -90, 1006 | align: 'right' 1007 | } 1008 | }, 1009 | yAxis: { 1010 | title: { 1011 | text: '' 1012 | }, 1013 | plotLines: [{ 1014 | value: 0, 1015 | width: 1, 1016 | color: '#808080' 1017 | }] 1018 | }, 1019 | plotOptions: { 1020 | series: { 1021 | stacking: 'normal' 1022 | } 1023 | }, 1024 | tooltip: { 1025 | formatter: function() { 1026 | return ''+ this.series.name +'
    '+ 1027 | this.x +': '+ this.y +''; 1028 | } 1029 | }, 1030 | legend: { 1031 | layout: 'vertical', 1032 | align: 'right', 1033 | verticalAlign: 'top', 1034 | x: -10, 1035 | y: 100, 1036 | borderWidth: 0 1037 | }, 1038 | series: seriesData 1039 | }); 1040 | } 1041 | else if(options.type=='line') 1042 | { 1043 | chart = new Highcharts.Chart({ 1044 | chart: { 1045 | renderTo: this.id, 1046 | type: 'line', 1047 | zoomType: 'x,y', 1048 | height: $(this.workspace.el).find('.workspace_results').height() - 40, 1049 | width: $(this.workspace.el).find('.workspace_results').width() - 40 1050 | }, 1051 | credits: { 1052 | text: 'Saiku Chart Plus Plugin by IT4biz', 1053 | href: 'http://it4biz.github.com/SaikuChartPlus' 1054 | }, 1055 | title: { 1056 | text: '', 1057 | x: -20 //center 1058 | }, 1059 | subtitle: { 1060 | text: '', 1061 | x: -20 1062 | }, 1063 | xAxis: { 1064 | categories: x, 1065 | labels: { 1066 | rotation: -90, 1067 | align: 'right' 1068 | } 1069 | }, 1070 | yAxis: { 1071 | title: { 1072 | text: '' 1073 | }, 1074 | plotLines: [{ 1075 | value: 0, 1076 | width: 1, 1077 | color: '#808080' 1078 | }] 1079 | }, 1080 | tooltip: { 1081 | formatter: function() { 1082 | return ''+ this.series.name +'
    '+ 1083 | this.x +': '+ this.y +''; 1084 | } 1085 | }, 1086 | legend: { 1087 | layout: 'vertical', 1088 | align: 'right', 1089 | verticalAlign: 'top', 1090 | x: -10, 1091 | y: 100, 1092 | borderWidth: 0 1093 | }, 1094 | series: seriesData 1095 | }); 1096 | } 1097 | else if(options.type=='pie') 1098 | { 1099 | chart = new Highcharts.Chart({ 1100 | chart: { 1101 | renderTo: this.id, 1102 | plotBackgroundColor: null, 1103 | plotBorderWidth: null, 1104 | plotShadow: false, 1105 | height: $(this.workspace.el).find('.workspace_results').height() - 40, 1106 | width: $(this.workspace.el).find('.workspace_results').width() - 40 1107 | }, 1108 | credits: { 1109 | text: 'Saiku Chart Plus Plugin by IT4biz', 1110 | href: 'http://it4biz.github.com/SaikuChartPlus' 1111 | }, 1112 | title: { 1113 | text: '' 1114 | }, 1115 | tooltip: { 1116 | pointFormat: '{series.name}: {point.percentage}%', 1117 | percentageDecimals: 1 1118 | }, 1119 | plotOptions: { 1120 | pie: { 1121 | allowPointSelect: true, 1122 | cursor: 'pointer', 1123 | dataLabels: { 1124 | enabled: true, 1125 | color: '#000000', 1126 | connectorColor: '#000000', 1127 | formatter: function() { 1128 | return ''+ this.point.name +': '+ this.percentage.toFixed(1) +' %'; 1129 | } 1130 | } 1131 | } 1132 | }, 1133 | series: seriesData 1134 | }); 1135 | } 1136 | else if(options.type=='geoChart') 1137 | { 1138 | var data = google.visualization.arrayToDataTable(series); 1139 | var optionsMap; 1140 | 1141 | if(options.region=='world'){ 1142 | optionsMap = { 1143 | width: $(this.workspace.el).find('.workspace_results').width() - 40, 1144 | height: $(this.workspace.el).find('.workspace_results').height() - 40, 1145 | datalessRegionColor: 'F5F5F5', 1146 | region: options.region, 1147 | displayMode: 'markers' 1148 | }; 1149 | }else{ 1150 | optionsMap = { 1151 | width: $(this.workspace.el).find('.workspace_results').width() - 40, 1152 | height: $(this.workspace.el).find('.workspace_results').height() - 40, 1153 | datalessRegionColor: 'F5F5F5', 1154 | region: options.region, 1155 | resolution: 'provinces', 1156 | displayMode: 'regions' 1157 | }; 1158 | } 1159 | 1160 | var geoChart = new google.visualization.GeoChart(document.getElementById(this.id)); 1161 | geoChart.draw(data, optionsMap); 1162 | 1163 | } 1164 | else if(options.type=='geoMap') 1165 | { 1166 | var data =new google.visualization.DataTable(); 1167 | data.addRows(series.length); 1168 | data.addColumn('string', series[0][0]); 1169 | data.addColumn('number', series[0][1]); 1170 | 1171 | for (var i=1; i < series.length; i++) { 1172 | data.setCell(i, 0, series[i][0]); 1173 | data.setCell(i, 1, series[i][1], series[i][2]); 1174 | }; 1175 | 1176 | var options = { 1177 | width: $(this.workspace.el).find('.workspace_results').width() - 40, 1178 | height: $(this.workspace.el).find('.workspace_results').height() - 40, 1179 | colors: [0xE0FFD4, 0xA5EF63, 0x50AA00, 0x267114], 1180 | region: options.region, 1181 | dataMode: 'regions' 1182 | }; 1183 | 1184 | var geoMap = new google.visualization.GeoMap(document.getElementById(this.id)); 1185 | google.visualization.events.addListener(geoMap, "error", function errorHandler(e) { 1186 | google.visualization.errors.removeError(e.id); 1187 | }); 1188 | 1189 | geoMap.draw(data, options); 1190 | 1191 | } 1192 | /*********End charts draw**************/ 1193 | }, 1194 | 1195 | receive_data: function(args) { 1196 | return _.delay(this.process_data, 0, args); 1197 | }, 1198 | 1199 | process_data: function(args) { 1200 | this.data = {}; 1201 | this.data.resultset = []; 1202 | this.data.metadata = []; 1203 | this.data.height = 0; 1204 | this.data.width = 0; 1205 | 1206 | if (args.data.cellset && args.data.cellset.length > 0) { 1207 | 1208 | var lowest_level = 0; 1209 | 1210 | for (var row = 0; row < args.data.cellset.length; row++) { 1211 | if (args.data.cellset[row][0].type == "ROW_HEADER_HEADER") { 1212 | this.data.metadata = []; 1213 | for (var field = 0; field < args.data.cellset[row].length; field++) { 1214 | if (args.data.cellset[row][field].type == "ROW_HEADER_HEADER") { 1215 | this.data.metadata.shift(); 1216 | lowest_level = field; 1217 | } 1218 | 1219 | this.data.metadata.push({ 1220 | colIndex: field, 1221 | colType: typeof(args.data.cellset[row + 1][field].value) !== "number" && 1222 | isNaN(args.data.cellset[row + 1][field].value 1223 | .replace(/[^a-zA-Z 0-9.]+/g,'')) ? "String" : "Numeric", 1224 | colName: args.data.cellset[row][field].value 1225 | }); 1226 | } 1227 | } else if (args.data.cellset[row][0].value !== "null" && args.data.cellset[row][0].value !== "") { 1228 | var record = []; 1229 | this.data.width = args.data.cellset[row].length; 1230 | for (var col = lowest_level; col < args.data.cellset[row].length; col++) { 1231 | var value = args.data.cellset[row][col].value; 1232 | // check if the resultset contains the raw value, if not try to parse the given value 1233 | if (args.data.cellset[row][col].properties.raw && args.data.cellset[row][col].properties.raw !== "null" && col>0) 1234 | { 1235 | value = parseFloat(args.data.cellset[row][col].properties.raw); 1236 | } else if (typeof(args.data.cellset[row][col].value) !== "number" && 1237 | parseFloat(args.data.cellset[row][col].value.replace(/[^a-zA-Z 0-9.]+/g,'')) && col>0) 1238 | { 1239 | value = parseFloat(args.data.cellset[row][col].value.replace(/[^a-zA-Z 0-9.]+/g,'')); 1240 | } 1241 | record.push(value); 1242 | } 1243 | this.data.resultset.push(record); 1244 | } 1245 | } 1246 | this.data.height = this.data.resultset.length; 1247 | this.render(); 1248 | } else { 1249 | $(this.el).text("No results"); 1250 | } 1251 | } 1252 | }); 1253 | 1254 | function loadCSS(file){ 1255 | 1256 | var headID = document.getElementsByTagName("head")[0]; 1257 | var cssNode = document.createElement('link'); 1258 | cssNode.type = 'text/css'; 1259 | cssNode.rel = 'stylesheet'; 1260 | cssNode.href = file; 1261 | cssNode.media = 'screen'; 1262 | headID.appendChild(cssNode); 1263 | } 1264 | 1265 | function loadJS(file){ 1266 | 1267 | var headID = document.getElementsByTagName("head")[0]; 1268 | var newScript = document.createElement('script'); 1269 | newScript.type = 'text/javascript'; 1270 | newScript.src = file; 1271 | headID.appendChild(newScript); 1272 | } 1273 | 1274 | /** 1275 | * Start Plugin 1276 | */ 1277 | Saiku.events.bind('session:new', function(session) { 1278 | 1279 | loadCSS('../saiku-chart-plus/css/plugin.css'); 1280 | 1281 | loadJS('//www.google.com/jsapi'); 1282 | loadJS("../saiku-chart-plus/js/google.js"); 1283 | 1284 | loadJS('../saiku-chart-plus/js/highcharts.js'); 1285 | loadJS('//code.highcharts.com/modules/exporting.js'); 1286 | 1287 | 1288 | function new_workspace(args) { 1289 | // Add stats element 1290 | if (typeof args.workspace.chartPlus == "undefined") { 1291 | args.workspace.chartPlus = new ChartPlus({ workspace: args.workspace }); 1292 | } 1293 | } 1294 | 1295 | function clear_workspace(args) { 1296 | if (typeof args.workspace.chartPlus != "undefined") { 1297 | $(args.workspace.chartPlus.nav).hide(); 1298 | $(args.workspace.chartPlus.el).parents().find('.workspace_results table').show(); 1299 | $(args.workspace.chartPlus.el).hide(); 1300 | } 1301 | } 1302 | 1303 | 1304 | // Attach stats to existing tabs 1305 | for(var i = 0; i < Saiku.tabs._tabs.length; i++) { 1306 | var tab = Saiku.tabs._tabs[i]; 1307 | new_workspace({ 1308 | workspace: tab.content 1309 | }); 1310 | }; 1311 | 1312 | // Attach stats to future tabs 1313 | Saiku.session.bind("workspace:new", new_workspace); 1314 | Saiku.session.bind("workspace:clear", clear_workspace); 1315 | }); 1316 | -------------------------------------------------------------------------------- /saiku-server/saiku-chart-plus/plugin.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2014 IT4biz IT Solutions Ltda 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * changed by it4biz.com.br 16 | */ 17 | 18 | /** 19 | * Renders a chart for each workspace 20 | */ 21 | var ChartPlus = Backbone.View.extend({ 22 | 23 | initialize: function(args) { 24 | this.workspace = args.workspace; 25 | 26 | // Create a unique ID for use as the CSS selector 27 | this.id = _.uniqueId("chartPlus_"); 28 | $(this.el).attr({ id: this.id }); 29 | 30 | // Bind table rendering to query result event 31 | _.bindAll(this, "render", "receive_data", "process_data", "show", 32 | "setOptions"); 33 | 34 | this.workspace.bind('query:result', this.receive_data); 35 | 36 | // Add chart button 37 | this.add_button(); 38 | this.workspace.toolbar.chartPlus = this.show; 39 | 40 | // Listen to adjust event and rerender chart 41 | this.workspace.bind('workspace:adjust', this.render); 42 | 43 | // Create navigation 44 | this.nav = $("
    "+ 45 | ""+ 627 | "
    "); 628 | 629 | 630 | 631 | 632 | 633 | this.nav.find('a').click(this.setOptions); 634 | 635 | //function for menu 636 | $("#nav ul ").css({display: "none"}); // Opera Fix 637 | $("#nav li").hover(function(){ 638 | $(this).find('ul:first').css({visibility: "visible",display: "none"}).show(400); 639 | },function(){ 640 | $(this).find('ul:first').css({visibility: "hidden"}); 641 | }); 642 | 643 | // Append chart to workspace 644 | $(this.workspace.el).find('.workspace_results') 645 | .prepend($(this.el).hide()) 646 | .prepend(this.nav.hide()); 647 | 648 | 649 | 650 | }, 651 | 652 | add_button: function() { 653 | var $chart_button = 654 | $('') 655 | .css({ 'background-image': "url('js/saiku/plugins/saiku-chart-plus/images/chart.png')", 656 | 'background-repeat':'no-repeat', 657 | 'background-position':'20% 50%' 658 | }); 659 | 660 | var $chart_li = $('
  • ').append($chart_button); 661 | $(this.workspace.toolbar.el).find("ul").append($chart_li); 662 | }, 663 | 664 | show: function(event, ui) { 665 | $(this.workspace.table.el).toggle(); 666 | $(this.el).toggle(); 667 | $(this.nav).toggle(); 668 | $(event.target).toggleClass('on'); 669 | 670 | if ($(event.target).hasClass('on')) { 671 | this.render(); 672 | } else { 673 | this.workspace.table.render({ data: this.workspace.query.result.lastresult() }); 674 | } 675 | }, 676 | 677 | setOptions: function(event) { 678 | var type = $(event.target).attr('href').replace('#', ''); 679 | var chartOptions=[]; 680 | chartOptions.type=type; 681 | 682 | try { 683 | if(type=='geoChart' || type=='geoMap'){ 684 | var region=$(event.target).attr('id'); 685 | chartOptions.region=region; 686 | this.render(chartOptions); 687 | }else 688 | this.render(chartOptions); 689 | } catch (e) { } 690 | 691 | return false; 692 | }, 693 | 694 | render: function(chartOptions) { 695 | 696 | if (! $(this.workspace.toolbar.el).find('.chartPlus').hasClass('on')) { 697 | return; 698 | } 699 | 700 | //configurações default 701 | var options = _.extend({ 702 | canvas: this.id, 703 | width: $(this.workspace.el).find('.workspace_results').width() - 40, 704 | height: $(this.workspace.el).find('.workspace_results').height() - 40, 705 | yAxisSize: 70, 706 | orientation: 'vertical', 707 | stacked: false, 708 | animate: false, 709 | showValues: false, 710 | legend: true, 711 | legendPosition:"top", 712 | legendAlign: "right", 713 | colors: ["#B40010", "#CCC8B4", "#DDB965", "#72839D", "#1D2D40"], 714 | serializeType: "highCharts", 715 | type: 'bar' 716 | }, chartOptions); 717 | 718 | //start serialization of data 719 | if(options.type!='pie' && options.type!='geoMap' && options.type!='geoChart'){ 720 | var metadata=new Array(); 721 | //numero de colunas 722 | var colNumberY=this.data.metadata.length-1;//-1 devido a coluna 0 armazena o valor de X 723 | var x=new Array(); 724 | var y=new Array(); 725 | for(var i=0; i < colNumberY; i++){ 726 | y[i]=new Array(); 727 | } 728 | 729 | 730 | if (this.data.resultset.length > 0 ) { 731 | $.each(this.data.resultset, function(key, value) { 732 | x[key]=value[0]; 733 | for(var i=0; i < colNumberY; i++){ 734 | y[i][key]=value[i+1];// +1 devido ao valor de x armazenado na coluna 0 735 | } 736 | 737 | }); 738 | } 739 | 740 | var seriesData=[]; 741 | for(var i=0; i < colNumberY; i++){ 742 | seriesData[i]={ 743 | name: this.data.metadata[i+1].colName, 744 | data: y[i] 745 | }; 746 | } 747 | }else if(options.type=='pie' && options.type!='geoMap' && options.type!='geoChart'){ 748 | if(this.data.metadata.length>0){ 749 | var metadata=new Array(); 750 | //numero de colunas 751 | var colNumber=this.data.metadata.length; 752 | var seriesData=new Array(); 753 | var series=new Array(); 754 | if (this.data.resultset.length > 0 ) { 755 | $.each(this.data.resultset, function(key, value) { 756 | series[key]=[value[0], value[1]]; 757 | }); 758 | } 759 | 760 | seriesData=[{ 761 | type: 'pie', 762 | name: this.data.metadata[0].colName, 763 | data: series 764 | }]; 765 | }else{ 766 | return false; 767 | } 768 | }else if(options.type=='geoMap'){ 769 | if(this.data.metadata.length>0){ 770 | var series=[]; 771 | //nome das colunas 772 | var column=[]; 773 | 774 | column[0]=this.data.metadata[0].colName; 775 | column[1]=this.data.metadata[1].colName; 776 | series[0]=column; 777 | 778 | 779 | if (this.data.resultset.length > 0 ) { 780 | var data= this.data; 781 | $.each(this.data.resultset, function(key, value) { 782 | var array=[]; 783 | array[0]=value[0]; 784 | array[1]=value[1]; 785 | array[2]=value[1]; 786 | for(var i=2; i < data.metadata.length; i++){ 787 | columnName=data.metadata[i].colName; 788 | value=value[i]; 789 | array[2]+=', '+columnName+': '+value; 790 | } 791 | series[key+1]=array; // +1 devido ao nome das colunas 792 | }); 793 | } 794 | 795 | }else{ 796 | return false; 797 | } 798 | 799 | }else{//options.type=='geoChart' 800 | var series=[]; 801 | //nome das colunas 802 | var column=[]; 803 | for(var i=0; i < this.data.metadata.length; i++) 804 | column[i]=this.data.metadata[i].colName; 805 | series[0]=column; 806 | 807 | if (this.data.resultset.length > 0 ) { 808 | $.each(this.data.resultset, function(key, value) { 809 | series[key+1]=value; // +1 devido ao nome das colunas 810 | }); 811 | } 812 | } 813 | //end serialization of data 814 | 815 | //start draw graphics 816 | if(options.type=='bar'){ 817 | chart = new Highcharts.Chart({ 818 | chart: { 819 | renderTo: this.id, 820 | type: 'bar', 821 | zoomType: 'x,y', 822 | height: $(this.workspace.el).find('.workspace_results').height() - 40, 823 | width: $(this.workspace.el).find('.workspace_results').width() - 40 824 | }, 825 | title: { 826 | text: '', 827 | x: -20 //center 828 | }, 829 | credits: { 830 | text: 'Saiku Chart Plus Plugin by IT4biz', 831 | href: 'http://it4biz.github.com/SaikuChartPlus' 832 | }, 833 | subtitle: { 834 | text: '', 835 | x: -20 836 | }, 837 | xAxis: { 838 | categories: x 839 | }, 840 | yAxis: { 841 | title: { 842 | text: '' 843 | }, 844 | plotLines: [{ 845 | value: 0, 846 | width: 1, 847 | color: '#808080' 848 | }] 849 | }, 850 | tooltip: { 851 | formatter: function() { 852 | return ''+ this.series.name +'
    '+ 853 | this.x +': '+ this.y +''; 854 | } 855 | }, 856 | legend: { 857 | layout: 'vertical', 858 | align: 'right', 859 | verticalAlign: 'top', 860 | x: -10, 861 | y: 100, 862 | borderWidth: 0 863 | }, 864 | series: seriesData 865 | }); 866 | } 867 | else if(options.type=='stackedBar') 868 | { 869 | chart = new Highcharts.Chart({ 870 | chart: { 871 | renderTo: this.id, 872 | type: 'bar', 873 | zoomType: 'x,y', 874 | height: $(this.workspace.el).find('.workspace_results').height() - 40, 875 | width: $(this.workspace.el).find('.workspace_results').width() - 40 876 | }, 877 | title: { 878 | text: '', 879 | x: -20 //center 880 | }, 881 | credits: { 882 | text: 'Saiku Chart Plus Plugin by IT4biz', 883 | href: 'http://it4biz.github.com/SaikuChartPlus' 884 | }, 885 | subtitle: { 886 | text: '', 887 | x: -20 888 | }, 889 | xAxis: { 890 | categories: x 891 | }, 892 | yAxis: { 893 | title: { 894 | text: '' 895 | }, 896 | plotLines: [{ 897 | value: 0, 898 | width: 1, 899 | color: '#808080' 900 | }] 901 | }, 902 | plotOptions: { 903 | series: { 904 | stacking: 'normal' 905 | } 906 | }, 907 | tooltip: { 908 | formatter: function() { 909 | return ''+ this.series.name +'
    '+ 910 | this.x +': '+ this.y +''; 911 | } 912 | }, 913 | legend: { 914 | layout: 'vertical', 915 | align: 'right', 916 | verticalAlign: 'top', 917 | x: -10, 918 | y: 100, 919 | borderWidth: 0 920 | }, 921 | series: seriesData 922 | }); 923 | } 924 | else if(options.type=='column') 925 | { 926 | chart = new Highcharts.Chart({ 927 | chart: { 928 | renderTo: this.id, 929 | type: 'column', 930 | zoomType: 'x,y', 931 | height: $(this.workspace.el).find('.workspace_results').height() - 40, 932 | width: $(this.workspace.el).find('.workspace_results').width() - 40 933 | }, 934 | credits: { 935 | text: 'Saiku Chart Plus Plugin by IT4biz', 936 | href: 'http://it4biz.github.com/SaikuChartPlus' 937 | }, 938 | title: { 939 | text: '', 940 | x: -20 //center 941 | }, 942 | subtitle: { 943 | text: '', 944 | x: -20 945 | }, 946 | xAxis: { 947 | categories: x, 948 | labels: { 949 | rotation: -90, 950 | align: 'right' 951 | } 952 | }, 953 | yAxis: { 954 | title: { 955 | text: '' 956 | }, 957 | plotLines: [{ 958 | value: 0, 959 | width: 1, 960 | color: '#808080' 961 | }] 962 | }, 963 | tooltip: { 964 | formatter: function() { 965 | return ''+ this.series.name +'
    '+ 966 | this.x +': '+ this.y +''; 967 | } 968 | }, 969 | legend: { 970 | layout: 'vertical', 971 | align: 'right', 972 | verticalAlign: 'top', 973 | x: -10, 974 | y: 100, 975 | borderWidth: 0 976 | }, 977 | series: seriesData 978 | }); 979 | } 980 | else if(options.type=='stackedColumn') 981 | { 982 | chart = new Highcharts.Chart({ 983 | chart: { 984 | renderTo: this.id, 985 | type: 'column', 986 | zoomType: 'x,y', 987 | height: $(this.workspace.el).find('.workspace_results').height() - 40, 988 | width: $(this.workspace.el).find('.workspace_results').width() - 40 989 | }, 990 | credits: { 991 | text: 'Saiku Chart Plus Plugin by IT4biz', 992 | href: 'http://it4biz.github.com/SaikuChartPlus' 993 | }, 994 | title: { 995 | text: '', 996 | x: -20 //center 997 | }, 998 | subtitle: { 999 | text: '', 1000 | x: -20 1001 | }, 1002 | xAxis: { 1003 | categories: x, 1004 | labels: { 1005 | rotation: -90, 1006 | align: 'right' 1007 | } 1008 | }, 1009 | yAxis: { 1010 | title: { 1011 | text: '' 1012 | }, 1013 | plotLines: [{ 1014 | value: 0, 1015 | width: 1, 1016 | color: '#808080' 1017 | }] 1018 | }, 1019 | plotOptions: { 1020 | series: { 1021 | stacking: 'normal' 1022 | } 1023 | }, 1024 | tooltip: { 1025 | formatter: function() { 1026 | return ''+ this.series.name +'
    '+ 1027 | this.x +': '+ this.y +''; 1028 | } 1029 | }, 1030 | legend: { 1031 | layout: 'vertical', 1032 | align: 'right', 1033 | verticalAlign: 'top', 1034 | x: -10, 1035 | y: 100, 1036 | borderWidth: 0 1037 | }, 1038 | series: seriesData 1039 | }); 1040 | } 1041 | else if(options.type=='line') 1042 | { 1043 | chart = new Highcharts.Chart({ 1044 | chart: { 1045 | renderTo: this.id, 1046 | type: 'line', 1047 | zoomType: 'x,y', 1048 | height: $(this.workspace.el).find('.workspace_results').height() - 40, 1049 | width: $(this.workspace.el).find('.workspace_results').width() - 40 1050 | }, 1051 | credits: { 1052 | text: 'Saiku Chart Plus Plugin by IT4biz', 1053 | href: 'http://it4biz.github.com/SaikuChartPlus' 1054 | }, 1055 | title: { 1056 | text: '', 1057 | x: -20 //center 1058 | }, 1059 | subtitle: { 1060 | text: '', 1061 | x: -20 1062 | }, 1063 | xAxis: { 1064 | categories: x, 1065 | labels: { 1066 | rotation: -90, 1067 | align: 'right' 1068 | } 1069 | }, 1070 | yAxis: { 1071 | title: { 1072 | text: '' 1073 | }, 1074 | plotLines: [{ 1075 | value: 0, 1076 | width: 1, 1077 | color: '#808080' 1078 | }] 1079 | }, 1080 | tooltip: { 1081 | formatter: function() { 1082 | return ''+ this.series.name +'
    '+ 1083 | this.x +': '+ this.y +''; 1084 | } 1085 | }, 1086 | legend: { 1087 | layout: 'vertical', 1088 | align: 'right', 1089 | verticalAlign: 'top', 1090 | x: -10, 1091 | y: 100, 1092 | borderWidth: 0 1093 | }, 1094 | series: seriesData 1095 | }); 1096 | } 1097 | else if(options.type=='pie') 1098 | { 1099 | chart = new Highcharts.Chart({ 1100 | chart: { 1101 | renderTo: this.id, 1102 | plotBackgroundColor: null, 1103 | plotBorderWidth: null, 1104 | plotShadow: false, 1105 | height: $(this.workspace.el).find('.workspace_results').height() - 40, 1106 | width: $(this.workspace.el).find('.workspace_results').width() - 40 1107 | }, 1108 | credits: { 1109 | text: 'Saiku Chart Plus Plugin by IT4biz', 1110 | href: 'http://it4biz.github.com/SaikuChartPlus' 1111 | }, 1112 | title: { 1113 | text: '' 1114 | }, 1115 | tooltip: { 1116 | pointFormat: '{series.name}: {point.percentage}%', 1117 | percentageDecimals: 1 1118 | }, 1119 | plotOptions: { 1120 | pie: { 1121 | allowPointSelect: true, 1122 | cursor: 'pointer', 1123 | dataLabels: { 1124 | enabled: true, 1125 | color: '#000000', 1126 | connectorColor: '#000000', 1127 | formatter: function() { 1128 | return ''+ this.point.name +': '+ this.percentage.toFixed(1) +' %'; 1129 | } 1130 | } 1131 | } 1132 | }, 1133 | series: seriesData 1134 | }); 1135 | } 1136 | else if(options.type=='geoChart') 1137 | { 1138 | var data = google.visualization.arrayToDataTable(series); 1139 | var optionsMap; 1140 | 1141 | if(options.region=='world'){ 1142 | optionsMap = { 1143 | width: $(this.workspace.el).find('.workspace_results').width() - 40, 1144 | height: $(this.workspace.el).find('.workspace_results').height() - 40, 1145 | datalessRegionColor: 'F5F5F5', 1146 | region: options.region, 1147 | displayMode: 'markers' 1148 | }; 1149 | }else{ 1150 | optionsMap = { 1151 | width: $(this.workspace.el).find('.workspace_results').width() - 40, 1152 | height: $(this.workspace.el).find('.workspace_results').height() - 40, 1153 | datalessRegionColor: 'F5F5F5', 1154 | region: options.region, 1155 | resolution: 'provinces', 1156 | displayMode: 'regions' 1157 | }; 1158 | } 1159 | 1160 | var geoChart = new google.visualization.GeoChart(document.getElementById(this.id)); 1161 | geoChart.draw(data, optionsMap); 1162 | 1163 | } 1164 | else if(options.type=='geoMap') 1165 | { 1166 | var data =new google.visualization.DataTable(); 1167 | data.addRows(series.length); 1168 | data.addColumn('string', series[0][0]); 1169 | data.addColumn('number', series[0][1]); 1170 | 1171 | for (var i=1; i < series.length; i++) { 1172 | data.setCell(i, 0, series[i][0]); 1173 | data.setCell(i, 1, series[i][1], series[i][2]); 1174 | }; 1175 | 1176 | var options = { 1177 | width: $(this.workspace.el).find('.workspace_results').width() - 40, 1178 | height: $(this.workspace.el).find('.workspace_results').height() - 40, 1179 | colors: [0xE0FFD4, 0xA5EF63, 0x50AA00, 0x267114], 1180 | region: options.region, 1181 | dataMode: 'regions' 1182 | }; 1183 | 1184 | var geoMap = new google.visualization.GeoMap(document.getElementById(this.id)); 1185 | google.visualization.events.addListener(geoMap, "error", function errorHandler(e) { 1186 | google.visualization.errors.removeError(e.id); 1187 | }); 1188 | 1189 | geoMap.draw(data, options); 1190 | 1191 | } 1192 | /*********End charts draw**************/ 1193 | }, 1194 | 1195 | receive_data: function(args) { 1196 | return _.delay(this.process_data, 0, args); 1197 | }, 1198 | 1199 | process_data: function(args) { 1200 | this.data = {}; 1201 | this.data.resultset = []; 1202 | this.data.metadata = []; 1203 | this.data.height = 0; 1204 | this.data.width = 0; 1205 | 1206 | if (args.data.cellset && args.data.cellset.length > 0) { 1207 | 1208 | var lowest_level = 0; 1209 | 1210 | for (var row = 0; row < args.data.cellset.length; row++) { 1211 | if (args.data.cellset[row][0].type == "ROW_HEADER_HEADER") { 1212 | this.data.metadata = []; 1213 | for (var field = 0; field < args.data.cellset[row].length; field++) { 1214 | if (args.data.cellset[row][field].type == "ROW_HEADER_HEADER") { 1215 | this.data.metadata.shift(); 1216 | lowest_level = field; 1217 | } 1218 | 1219 | this.data.metadata.push({ 1220 | colIndex: field, 1221 | colType: typeof(args.data.cellset[row + 1][field].value) !== "number" && 1222 | isNaN(args.data.cellset[row + 1][field].value 1223 | .replace(/[^a-zA-Z 0-9.]+/g,'')) ? "String" : "Numeric", 1224 | colName: args.data.cellset[row][field].value 1225 | }); 1226 | } 1227 | } else if (args.data.cellset[row][0].value !== "null" && args.data.cellset[row][0].value !== "") { 1228 | var record = []; 1229 | this.data.width = args.data.cellset[row].length; 1230 | for (var col = lowest_level; col < args.data.cellset[row].length; col++) { 1231 | var value = args.data.cellset[row][col].value; 1232 | // check if the resultset contains the raw value, if not try to parse the given value 1233 | if (args.data.cellset[row][col].properties.raw && args.data.cellset[row][col].properties.raw !== "null" && col>0) 1234 | { 1235 | value = parseFloat(args.data.cellset[row][col].properties.raw); 1236 | } else if (typeof(args.data.cellset[row][col].value) !== "number" && 1237 | parseFloat(args.data.cellset[row][col].value.replace(/[^a-zA-Z 0-9.]+/g,'')) && col>0) 1238 | { 1239 | value = parseFloat(args.data.cellset[row][col].value.replace(/[^a-zA-Z 0-9.]+/g,'')); 1240 | } 1241 | record.push(value); 1242 | } 1243 | this.data.resultset.push(record); 1244 | } 1245 | } 1246 | this.data.height = this.data.resultset.length; 1247 | this.render(); 1248 | } else { 1249 | $(this.el).text("No results"); 1250 | } 1251 | } 1252 | }); 1253 | 1254 | function loadCSS(file){ 1255 | 1256 | var headID = document.getElementsByTagName("head")[0]; 1257 | var cssNode = document.createElement('link'); 1258 | cssNode.type = 'text/css'; 1259 | cssNode.rel = 'stylesheet'; 1260 | cssNode.href = file; 1261 | cssNode.media = 'screen'; 1262 | headID.appendChild(cssNode); 1263 | } 1264 | 1265 | function loadJS(file){ 1266 | 1267 | var headID = document.getElementsByTagName("head")[0]; 1268 | var newScript = document.createElement('script'); 1269 | newScript.type = 'text/javascript'; 1270 | newScript.src = file; 1271 | headID.appendChild(newScript); 1272 | } 1273 | 1274 | /** 1275 | * Start Plugin 1276 | */ 1277 | Saiku.events.bind('session:new', function(session) { 1278 | 1279 | loadCSS('js/saiku/plugins/saiku-chart-plus/css/plugin.css'); 1280 | 1281 | loadJS('//www.google.com/jsapi'); 1282 | loadJS("js/saiku/plugins/saiku-chart-plus/js/google.js"); 1283 | 1284 | loadJS('js/saiku/plugins/saiku-chart-plus/js/highcharts.js'); 1285 | loadJS('//code.highcharts.com/modules/exporting.js'); 1286 | 1287 | 1288 | function new_workspace(args) { 1289 | // Add stats element 1290 | if (typeof args.workspace.chartPlus == "undefined") { 1291 | args.workspace.chartPlus = new ChartPlus({ workspace: args.workspace }); 1292 | } 1293 | } 1294 | 1295 | function clear_workspace(args) { 1296 | if (typeof args.workspace.chartPlus != "undefined") { 1297 | $(args.workspace.chartPlus.nav).hide(); 1298 | $(args.workspace.chartPlus.el).parents().find('.workspace_results table').show(); 1299 | $(args.workspace.chartPlus.el).hide(); 1300 | } 1301 | } 1302 | 1303 | 1304 | // Attach stats to existing tabs 1305 | for(var i = 0; i < Saiku.tabs._tabs.length; i++) { 1306 | var tab = Saiku.tabs._tabs[i]; 1307 | new_workspace({ 1308 | workspace: tab.content 1309 | }); 1310 | }; 1311 | 1312 | // Attach stats to future tabs 1313 | Saiku.session.bind("workspace:new", new_workspace); 1314 | Saiku.session.bind("workspace:clear", clear_workspace); 1315 | }); 1316 | --------------------------------------------------------------------------------