PrimeFaces p:barChart settings - primefaces

I'm trying to use the PrimeFaces chart bar component. I configured some settings, but I am having problems with some settings. I want to completely remove the part I put in the yellow box. I also want to shorten the area indicated by the green arrow. How can I do it?
The settings on the xhtml and bean side are as follows.
xhtml:
<p:panel>
<f:facet name="header">
<span style="float: left;">Toplam Kazancınız</span>
<span style="float: right;">#{toplamKazancBean.kko.kazancToplam} TRY</span>
</f:facet>
<p:barChart model="#{toplamKazancBean.stackedBarModel}" style="width: 100%; height: 150px;" />
</p:panel>
bean:
private void chartSettings() {
// values:
stackedBarModel = new HorizontalBarChartModel();
ChartData data = new ChartData();
HorizontalBarChartDataSet barDataSet = new HorizontalBarChartDataSet();
for (int i = 0; i < kko.getKazanclarList().size(); i++) {
int oran = (int) Math.floor(kko.getKazanclarList().get(i).getTutar() / kko.getKazancToplam() * 100);
barDataSet.setLabel(kko.getKazanclarList().get(i).getMetinAlani() + " %" + oran);
barDataSet.setBackgroundColor(rgbArray[i]);
List<Number> dataVal = new ArrayList<Number>();
dataVal.add(kko.getKazanclarList().get(i).getTutar());
barDataSet.setData(dataVal);
data.addChartDataSet(barDataSet);
}
stackedBarModel.setData(data);
// Options
CartesianScaleLabel label = new CartesianScaleLabel();
label.setDisplay(false);
AxesGridLines gridLines = new AxesGridLines();
gridLines.setDisplay(false);//ızgaralar kapandı
CartesianLinearAxes linearAxes = new CartesianLinearAxes();
linearAxes.setStacked(true);
linearAxes.setGridLines(gridLines);
linearAxes.setScaleLabel(label);
CartesianScales cScales = new CartesianScales();
cScales.addXAxesData(linearAxes);
cScales.addYAxesData(linearAxes);
cScales.setDisplay(true);
Tooltip tooltip = new Tooltip();
tooltip.setEnabled(false);
BarChartOptions options = new BarChartOptions();
options.setScales(cScales);
options.setTooltip(tooltip);
options.setOffsetGridLines(false);
stackedBarModel.setOptions(options);
}

Related

Use the browser local storage with JSF2 and Primefaces

Hi this is not strictly a question, I would like to share my solution to use the browser local storage with JSF2 and Primefaces.
I found very little information on using local storage with jsf2 and primefaces, so it seemed useful to share my work.
The backing bean:
#Component("pocLocalStorageBean")
#Scope(WebApplicationContext.SCOPE_REQUEST)
public class PocLocalStorageBean {
private static final long serialVersionUID = 1L;
private String[] selectedCities;
private List<String> cities;
#PostConstruct
public void initialize() {
List<String> cities = new ArrayList<String>();
cities.add("Miami");
cities.add("London");
cities.add("Paris");
cities.add("Istanbul");
cities.add("Berlin");
cities.add("Barcelona");
cities.add("Rome");
cities.add("Brasilia");
cities.add("Amsterdam");
setCities(cities);
}
//GETTER E SETTER HERE
}
The page xhtml:
<h:form id="yuorFormId" cache="false">
<p:remoteCommand name="updateUiAfterLoadChoicesFromLocalStorage" update=":yuorFormId:yourSelectManyCheckboxId">
</p:remoteCommand>
<p:remoteCommand oncomplete="loadCitiesChoicesFromLocalStorage(#{pocLocalStorageBean.cities.size()});" autoRun="true">
</p:remoteCommand>
<div class="ui-g ui-fluid">
<div class="ui-g-12 ui-md-12">
<div class="card">
<p:selectManyCheckbox id="yourSelectManyCheckboxId" value="#{pocLocalStorageBean.selectedCities}" layout="responsive" columns="3">
<f:selectItems value="#{pocLocalStorageBean.cities}" var="city" itemLabel="#{city}" itemValue="#{city}"/>
<p:ajax oncomplete="setCitiesChoicesToLocalStorage(#{pocLocalStorageBean.cities.size()})"/>
</p:selectManyCheckbox>
</div>
</div>
</div>
</h:form>
And the javascript functions:
function findPreviousChoose(arrayChoicesFromLocalStorage,valueToFind){
if(arrayChoicesFromLocalStorage != null && arrayChoicesFromLocalStorage.length > 0){
var arrayLength = arrayChoicesFromLocalStorage.length;
for (var j = 0; j < arrayLength; j++) {
var iteratedChoose = arrayChoicesFromLocalStorage[j];
if(iteratedChoose!=null){
if(iteratedChoose.value == valueToFind){
return iteratedChoose;
}
}
}
}
return null;
}
function parseSafeJSON(str){
try {
if(str!=null){
var obj = JSON.parse(str);
return obj;
}
} catch (ex) {
return null;
}
return null;
}
function loadCitiesChoicesFromLocalStorage(citiesNumber){
var arrayChoicesFromLocalStorageStringed = localStorage.getItem('CITIES_LOCAL_STORE_KEY');
if(arrayChoicesFromLocalStorageStringed!=null){
var arrayChoicesFromLocalStorage = parseSafeJSON(arrayChoicesFromLocalStorageStringed);
var elementId = 'yuorFormId:yourSelectManyCheckboxId';
var element = document.getElementById(elementId);
var i;
for (i = 0; i < citiesNumber; i++) {
var elementIterated = document.getElementById(elementId+':'+i);
var valueIterated = elementIterated.value;
var previousChoose = findPreviousChoose(arrayChoicesFromLocalStorage,valueIterated);
if(previousChoose != null) {
elementIterated.defaultChecked = previousChoose.defaultChecked;
}
}
//update the needed components:
updateUiAfterLoadChoicesFromLocalStorage();
}
}
function setCitiesChoicesToLocalStorage(citiesNumber) {
var elementId = 'yuorFormId:yourSelectManyCheckboxId';
var element = document.getElementById(elementId);
var i;
var arrayChoices = new Array();
for (i = 0; i < citiesNumber; i++) {
var elementIterated = document.getElementById(elementId+':'+i);
var valueIterated = elementIterated.value;
var defaultCheckedIterated = elementIterated.checked;
var objIterated = { "value":valueIterated, "defaultChecked":defaultCheckedIterated};
arrayChoices.push(objIterated);
}
var storageValuesArray = JSON.stringify(arrayChoices);
localStorage.setItem('CITIES_LOCAL_STORE_KEY', storageValuesArray);
}
I also reported my solution to the primefaces forum:
https://forum.primefaces.org/viewtopic.php?f=3&t=39051&p=180978#p180978
If you don't use primefaces but only jsf 2.3 it shoud work with h:commandScript instead of p:remoteCommand (but I have not tried):
How to invoke a JSF managed bean on a HTML DOM event using native JavaScript?
I don't know the solution for those who use jsf < 2.3 without primefaces (any suggestions for this scenario are welcome)

How to set font in excel using customized data exporter in Primefaces?

I am using primefaces 6.1. I need to export my report list to excel format.For this i used primefaces data exporter.Dataexporter is giving me excel format. I have also set font in the excel. But the font is not completely working in my excel file.The set font appears in the table header only.
My Code is like this:
public void postProcessXLS(Object document) {
HSSFWorkbook wb = (HSSFWorkbook) document;
HSSFSheet sheet = wb.getSheetAt(0);
HSSFRow header = sheet.getRow(0);
HSSFCellStyle cellStyle = wb.createCellStyle();
cellStyle.setFillForegroundColor(HSSFColor.AQUA.index);
cellStyle.setFillPattern(HSSFCellStyle.SOLID_FOREGROUND);
HSSFFont fontHeader = (HSSFFont) wb.createFont();
cellStyle.setAlignment(HSSFCellStyle.ALIGN_CENTER);
fontHeader.setFontName("Magnus Nepali");
cellStyle.setFont(fontHeader);
for(int i=0; i < header.getPhysicalNumberOfCells();i++) {
HSSFCell cell = header.getCell(i);
cell.setCellStyle(cellStyle);
}
}
My button code is :
<p:commandButton id="excel" ajax="false">
<p:dataExporter type="xls" target="tblReport" fileName="report" postProcessor="#{shareDividendMB.postProcessXLS}" />
</p:commandButton>
My excel format is like this:
Only excel sheet header has changed to font defined and the remaining data have Arial font.I tried other than my font and the result is same.
Finally i got the solution.My working code is like this:
public void postProcessXLS(Object document) {
HSSFWorkbook wb = (HSSFWorkbook) document;
HSSFSheet sheet = wb.getSheetAt(0);
HSSFCellStyle cellStyle = wb.createCellStyle();
cellStyle.setFillForegroundColor(HSSFColor.AQUA.index);
cellStyle.setFillPattern(HSSFCellStyle.SOLID_FOREGROUND);
HSSFFont fontHeader = (HSSFFont) wb.createFont();
cellStyle.setAlignment(HSSFCellStyle.ALIGN_CENTER);
fontHeader.setFontName("Magnus Nepali");
cellStyle.setFont(fontHeader);
for (Row row : sheet) {
for (Cell cell : row) {
cell.setCellStyle(cellStyle);
}
}
}

Why do I get label displacement when I export a pie or line chart?

I have been trying to figure out why this happens for quite a while. My page have three kinds of charts: bar, line and pie models. The pie and line gets labels displacement when I export it and the bar its just fine.
I think it has something to do with jqplot css. But still, it is quite frustrating.
My pie chart is in a dialog...
xhtml code:
<p:dialog id="expanded-mission-distribution-dialog" resizable="false"
widgetVar="expanded-mission-distribution-dialog-var" modal="true"
dynamic="true">
<p:panel id="expanded-mission-distribution-panel"
styleClass="expanded-chart-panel ">
<p:chart id="expanded-mission-distribution-chart" type="pie"
styleClass="jqplot-target legend-spacing legend-size chart-dimension-3"
widgetVar="expanded-mission-distribution-chart-var"
model="#{fatigueDataSummaryAircraftAnalysisH.expandedMissionDistributionChart}" />
<p:commandButton id="mission-distribution-export-button"
type="button" icon="ui-circle-export" styleClass="ui-command-button"
title="Click to save the chart as image"
onclick="exportChart('expanded-mission-distribution-chart-var')" />
</p:panel>
</p:dialog>
The javascript that exports charts (I had to use a different approach compared to the one used in Primefaces' showcase, due compatibility purposes):
function b64toBlob(b64Data, contentType, sliceSize) {
contentType = contentType || '';
sliceSize = sliceSize || 512;
var byteCharacters = atob(b64Data);
var byteArrays = [];
for (var offset = 0; offset < byteCharacters.length; offset += sliceSize) {
var slice = byteCharacters.slice(offset, offset + sliceSize);
var byteNumbers = new Array(slice.length);
for (var i = 0; i < slice.length; i++) {
byteNumbers[i] = slice.charCodeAt(i);
}
var byteArray = new Uint8Array(byteNumbers);
byteArrays.push(byteArray);
}
var blob = new Blob(byteArrays, {type: contentType});
return blob;
}
function exportChart(chart) {
// Exportando o gráfico como uma imagem.
var image = PF(chart).exportAsImage();
var fileName = "image.png";
var src = image.getAttribute('src');
var type = 'image/png';
var b64Data = src.split(',')[1];
var blob = b64toBlob(b64Data, type);
var link = document.createElement("a");
if (link.download !== undefined) { // feature detection
// Browsers that support HTML5 download attribute
link.setAttribute("href", window.URL.createObjectURL(blob));
link.setAttribute("download", fileName);
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
} else {
alert('Chart export only works in Chrome (v20+), Firefox (Gecko v13+), IE (v10+), Safari (v6+) and Opera (v12.10+).');
}
Image of chart in dialog:
Pie chart inside my dialog
Image of exported chart:
Exported pie chart
There is nothing similar over internet or whatsoever, what could be the reason of this issue?

getelementbyid issue with radio button

I'm trying to make an alert with the value of the selected radio button, but I allways get the first of them, regardless the one I choose...(Acompanhado);
html:
<form/>
<input type="radio" class="simple_form" name="grupo_1" value="Acompanhado" id="saida"/>
<span class="texto">Acompanhado</span>
<input type="radio" class="simple_form" name="grupo_1" value="Individual" id="saida"/>
<span class="texto">Individual</span>
</form>
js:
function save() {
var saida_js = document.getElementById('saida').value;
alert("Tipo de saida: " + saida_js);
}
Any idea ?
#Quentin: I have alot of alerts, cause Im trying to get all data from a form. I used your code, and I get no alert at all.
function save() {
var morada_js = document.getElementById('morada').value;
var data_js = document.getElementById('data').value;
var hora_js = document.getElementById('hora').value;
var radio_saida = document.getElementsByName('name_saida');
var notas_js = document.getElementById('notas').value;
var condicoes_atm_js = document.getElementById('condicoes_atm').value;
alert("Morada: " + morada_js);
alert("Data: " + data_js);
alert("Hora: " + hora_js);
function get_checked_radio(radio_saida) {
for (var i = 0; i < radio_saida.length; i++) {
var current = radio_saida[i];
if (current.checked) {
return current;
}
}
}
alert(get_checked_radio(radio_saida).value);
alert("Notas: " + notas_js);
}
An id must be unique in a document.
To find the value of a selected radio button in a group, get the group by its name…
var radios = document.getElementsByName('radio_name'); // or
var radios = document.forms.formId.elements.radio_name;
Then loop over them until you find the one with the true checked property.
function get_checked_radio(radios) {
for (var i = 0; i < radios.length; i++) {
var current = radios[i];
if (current.checked) {
return current;
}
}
}
alert(get_checked_radio(radios).value);
Makes sense because you've got two input tags with the same id saida

How do I integrate Salesforce with Google Maps?

How do I integrate Salesforce with Google Maps? I'm just looking for information on how to...
Search for contacts in Salesforce
Plot those on a google map.
EDIT:
Thanks to tggagne's comment I've realized that people still see this answer. The code that was here is over 2.5 years old. If you want to see it - check the history of edits.
A lot has changed in the meantime, more mashup examples were created. Not the least of them being "SF Bus Radar" (github, youtube) app by Cory Cowgill (created on Dreamforce'11 I think).
Nonetheless - here's my updated example with server-side geocoding, new field of type Geolocation and usage of JSON parsers.
It tries to cache the geocoding results in the contact records. Bear in mind it might not be 'production-ready' (no Google Business API key = as all our requests come out from same pool of Salesforce IP servers there might be error messages). That's why I've left the client-side geocoding too.
You'll need to make 2 changes in your environment before checking it out:
Add "Remote Site Setting" that points to https://maps.googleapis.com to enable callouts from Apex
Add field "Location" in Setup -> Customize -> Contacts -> fields. Type should be "Geolocation". I've selected display as decimals and precision of 6 decimal places.
public with sharing class mapController {
public String searchText {get;set;}
public List<Contact> contacts{get; private set;}
public static final String GEOCODING_URI_BASE = 'https://maps.googleapis.com/maps/api/geocode/json?sensor=false&address=';
// For purposes of this demo I'll geocode only couple of addresses server-side. Real code can use the commented out value.
public static final Integer MAX_CALLOUTS_FROM_APEX = 3; // Limits.getLimitCallouts()
public mapController(){
searchText = ApexPages.currentPage().getParameters().get('q');
}
public void find() {
if(searchText != null && searchText.length() > 1){
List<List<SObject>> results = [FIND :('*' + searchText + '*') IN ALL FIELDS RETURNING
Contact (Id, Name, Email, Account.Name,
MailingStreet, MailingCity, MailingPostalCode, MailingState, MailingCountry,
Location__Latitude__s, Location__Longitude__s)
];
contacts = (List<Contact>)results[0];
if(contacts.isEmpty()){
ApexPages.addMessage(new ApexPages.Message(ApexPages.Severity.INFO, 'No matches for "' + searchText + '"'));
} else {
serverSideGeocode();
}
} else {
if(contacts != null) {
contacts.clear();
}
ApexPages.addMessage(new ApexPages.Message(ApexPages.Severity.INFO, 'Please provide at least 2 characters for the search.'));
}
}
public void clearGeocodedData(){
for(Contact c : contacts){
c.Location__Latitude__s = c.Location__Longitude__s = null;
}
Database.update(contacts, false);
contacts.clear();
}
public String getContactsJson(){
return JSON.serialize(contacts);
}
public String getDebugContactsJson(){
return JSON.serializePretty(contacts);
}
private void serverSideGeocode(){
List<Contact> contactsToUpdate = new List<Contact>();
Http h = new Http();
HttpRequest req = new HttpRequest();
req.setMethod('GET');
req.setTimeout(10000);
for(Contact c : contacts){
if((c.Location__Latitude__s == null || c.Location__Longitude__s == null)){
String address = c.MailingStreet != null ? c.MailingStreet + ' ' : '' +
c.MailingCity != null ? c.MailingCity + ' ' : '' +
c.MailingState != null ? c.MailingState + ' ' : '' +
c.MailingPostalCode != null ? c.MailingPostalCode + ' ' : '' +
c.MailingCountry != null ? c.MailingCountry : '';
if(address != ''){
req.setEndpoint(GEOCODING_URI_BASE + EncodingUtil.urlEncode(address, 'UTF-8'));
try{
HttpResponse res = h.send(req);
GResponse gr = (GResponse) JSON.deserialize(res.getBody(), mapController.GResponse.class);
if(gr.status == 'OK'){
LatLng ll = gr.results[0].geometry.location;
c.Location__Latitude__s = ll.lat;
c.Location__Longitude__s = ll.lng;
contactsToUpdate.add(c);
} else {
ApexPages.addMessage(new ApexPages.Message(ApexPages.Severity.ERROR, 'Geocoding of "' + address + '" failed:' + gr.status));
}
}catch(Exception e){
ApexPages.addMessages(e);
}
}
// Bail out if we've reached limit of callouts (not all contacts might have been processed).
if(Limits.getCallouts() == MAX_CALLOUTS_FROM_APEX) {
break;
}
}
}
if(!contactsToUpdate.isEmpty()) {
Database.update(contactsToUpdate, false); // some data in Developer editions is invalid (on purpose I think).
// If update fails because "j.davis#expressl&t.net" is not a valid Email, I want the rest to succeed
}
}
// Helper class - template into which results of lookup will be parsed. Some fields are skipped!
// Visit https://developers.google.com/maps/documentation/geocoding/#Results if you need to create full mapping.
public class GResponse{
public String status;
public GComponents[] results;
}
public class GComponents{
public String formatted_address;
public GGeometry geometry;
}
public class GGeometry {
public LatLng location;
}
public class LatLng{
public Double lat, lng;
}
}
<apex:page controller="mapController" tabStyle="Contact" action="{!find}" id="page">
<head>
<style>
div #map_canvas { height: 400px; }
</style>
<script type="text/javascript" src="https://maps.googleapis.com/maps/api/js?sensor=false"></script>
</head>
<apex:sectionHeader title="Hello StackOverflow!" subtitle="Contact full text search + Google Maps integration" />
<apex:pageMessages />
<apex:form id="form">
<apex:pageBlock id="searchBlock">
<apex:inputText value="{!searchText}" />
<apex:commandButton value="Search" action="{!find}"/>
<p>Examples: "USA", "Singapore", "Uni", "(336) 222-7000". If it works in the global search box, it will work here.</p>
</apex:pageBlock>
<apex:pageBlock title="Found {!contacts.size} Contact(s)..." rendered="{!NOT(ISNULL(contacts)) && contacts.size > 0}" id="resultsBlock">
<apex:pageBlockButtons location="top">
<apex:commandButton value="Clear cached locations" title="Click if you want to set 'null' as geolocation info for all these contacts" action="{!clearGeocodedData}" />
</apex:pageBlockButtons>
<apex:pageBlockTable value="{!contacts}" var="c" id="contacts">
<apex:column headerValue="{!$ObjectType.Contact.fields.Name.label}">
<apex:outputLink value="../{!c.Id}">{!c.Name}</apex:outputLink>
</apex:column>
<apex:column headerValue="Address">
{!c.MailingStreet} {!c.MailingCity} {!c.MailingCountry}
</apex:column>
<apex:column value="{!c.Account.Name}"/>
<apex:column headerValue="Location (retrieved from DB or geocoded server-side)">
{!c.Location__Latitude__s}, {!c.Location__Longitude__s}
</apex:column>
</apex:pageBlockTable>
<apex:pageBlockSection columns="1" id="mapSection">
<div id="map_canvas" />
</apex:pageBlockSection>
<apex:pageBlockSection title="Click to show/hide what was geocoded server-side and passed to JS for further manipulation" columns="1" id="debugSection">
<pre>{!debugContactsJson}</pre>
</apex:pageBlockSection>
<pre id="log"></pre>
</apex:pageBlock>
</apex:form>
<script type="text/javascript">
twistSection(document.getElementById('page:form:resultsBlock:debugSection').childNodes[0].childNodes[0]); // initially hide the debug section
var contacts = {!contactsJson}; // Array of contact data, some of them might have lat/long info, some we'll have to geocode client side
var coords = []; // Just the latitude/longitude for each contact
var requestCounter = 0;
var markers = []; // Red things we pin to the map.
var balloon = new google.maps.InfoWindow(); // Comic-like baloon that floats over markers.
function geocodeClientSide() {
for(var i = 0; i < contacts.length; i++) {
if(contacts[i].Location__Latitude__s != null && contacts[i].Location__Longitude__s != null) {
coords.push(new google.maps.LatLng(contacts[i].Location__Latitude__s, contacts[i].Location__Longitude__s));
} else {
++requestCounter;
var address = contacts[i].MailingStreet + ' ' + contacts[i].MailingCity + ' ' + contacts[i].MailingCountry;
var geocoder = new google.maps.Geocoder();
if (geocoder) {
geocoder.geocode({'address':address}, function (results, status) {
if (status == google.maps.GeocoderStatus.OK) {
coords.push(results[0].geometry.location);
} else {
var pTag = document.createElement("p");
pTag.innerHTML = status;
document.getElementById('log').appendChild(pTag);
}
if(--requestCounter == 0) {
drawMap();
}
});
}
}
}
// It could be the case that all was geocoded on server side (or simply retrieved from database).
// So if we're lucky - just proceed to drawing the map.
if(requestCounter == 0) {
drawMap();
}
}
function drawMap(){
var mapOptions = {
center: coords[0],
zoom: 3,
mapTypeId: google.maps.MapTypeId.ROADMAP
};
var map = new google.maps.Map(document.getElementById("map_canvas"), mapOptions);
for(var i = 0; i < coords.length; ++i){
var marker = new google.maps.Marker({map: map, position: coords[i], title:contacts[i].Name, zIndex:i});
google.maps.event.addListener(marker, 'click', function() {
var index = this.zIndex;
balloon.content = '<b>'+contacts[index].Name + '</b><br/>' + contacts[index].Account.Name + '<br/>' + contacts[index].Email;
balloon.open(map,this);
});
markers.push(marker);
}
}
geocodeClientSide();
</script>
</apex:page>
Another place to look is the force.com platform fundamentals book (or site if you don't have a developer account). They have a very good and detailed tutorial here showing how to integrate maps with Salesforce (they use Yahoo for the tutorial but it will work just as well with Google Maps).
Since Spring '15, we can also use apex:map with no extra Google API.
Also works when viewed in Lightning -- No personal experience specifically but that's what I read.
Example from Docs:
<apex:map width="600px" height="400px" mapType="roadmap" center="{!Account.BillingStreet}, {!Account.BillingCity}, {!Account.BillingState}">
<!-- Add a CUSTOM map marker for the account itself -->
<apex:mapMarker title="{! Account.Name }" position="{!Account.BillingStreet}, {!Account.BillingCity}, {!Account.BillingState}" icon="{! URLFOR($Resource.MapMarkers, 'moderntower.png') }"/>
<!-- Add STANDARD markers for the account's contacts -->
<apex:repeat value="{! Account.Contacts }" var="ct">
<apex:mapMarker title="{! ct.Name }" position="{! ct.MailingStreet }, {! ct.MailingCity }, {! ct.MailingState }"></apex:mapMarker>
</apex:repeat>
</apex:map>
In the example, {! Account.Contacts } is a list of Contacts which
is being iterated over. Each iteration, it's creating apex:mapMarker's to map all Contacts in a list. Though the OP is old, the "search results" could basically replace the {Account.Contacts} list being iterated over in example.
Documentation:
Docs that example was pulled from.
(I know this is old but was brought to top from an update so thought update not using API would be okay.)