Using FusionCharts with Ext JS - extjs

I am thinking about using FusionCharts in an application entirely build with Ext JS so far.
However, I don't believe there's a specific recommended implementation or connector to easily add FusionCharts to an Ext JS app. There are various examples online of others adding the charts within an Ext JS app though:
http://jsfiddle.net/fusioncharts/xujmxjcb/
http://jsfiddle.net/fusioncharts/5j8s7g68/
https://www.sencha.com/forum/showthread.php?218834-How-to-integrate-fusion-charts-with-Extjs4&p=830921&viewfull=1#post830921
The last one discusses a way to create an Ext JS class for FusionCharts that "wraps" some of the charting functionality within a proper class:
/* * ?????? : var testdata = { part : { 'Jul 01' : 2000, 'Aug 02' : 2400, 'Sep 03' : 2000, 'Oct 04' :
* "", 'Dec 05' : null }, zoo : { 'Jul 01' : 4000, 'Aug 02' : 3400, // 'Sep 03' : 3000, // 'Oct 04' :
* 5200, 'Dec 05' : 4210 }, hotel : { // 'Jul 01' : 6000, 'Aug 02' : 6400, // 'Sep 03' : 7000, 'Oct
* 04' : 8200, 'Dec 05' : 8100 } }; // this.setChartData(testdata); ????????????
*/
/**
* ????
* #class Ext.ux.MSLineChart
* #extends Ext.Panel
* #cgf initData : Object ??????.
* #cgf DwrAction : DWR???? ??????.
* #cgf baseLoadParam : Object DWR???????.
* #cgf autoShowChart : boolean ??(true) ??????????.
* #function loadData() : ??DWR????,????.
* #cgf imageType ???? : MSColumn2D,MSColumn3D,MSLine,MSArea,MSBar2D,MSBar3D StackedColumn2D,
* StackedColumn3D,StackedArea2D,StackedBar2D,StackedBar2D,StackedBar3D
*/
Ext.ux.FusionChart = Ext.extend(Ext.Panel, {
width : 1000,
height : 600,
border : false,
layout : 'fit',
autoShowChart : true,
animationflex : true,
imageType : 'MSLine',
constructor : function(config) {
Ext.apply(this, config);
this.isLineChart = true; // ??????????
var chartDom = Ext.core.DomHelper.append(document.body, {
id : 'ux-fc-' + ++Ext.AbstractComponent.AUTO_ID,
tag : 'div',
cls : 'x-hidden',
style : 'z-index:-1;width:100%;height:100%'
});
this.chart = new FusionCharts(WEBPATH + '/common/fc/' + this.imageType + '.swf', chartDom.id, '100%', "100%", "0",
"1", null);
this.chart.addParam("wmode", "transparent");// ???,????EXT
if (this.initData) {
this.setChartData(this.initData);
} else if (this.DwrAction && this.autoShowChart === true) {
this.loadData(this.baseLoadParam);
}
this.contentEl = this.chart.getAttribute('id');
Ext.ux.FusionChart.superclass.constructor.call(this);
this.on('render', this.renderPanel, this);
},
renderPanel : function() {
},
/** ??DWR??????. */
loadData : function(param) {
param = param || {};
Ext.applyIf(param, this.baseLoadParam);
var setChartData = Ext.bind(this.setChartData, this);
this.DwrAction(param, setChartData);
},
// ??????XML???render chart
setChartData : function(data) {
var animation = this.animationflex == true ? 1 : 0;
var DataXML = "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<chart animation =\"" + animation
+ "\" baseFont=\"??\" baseFontSize=\"12\">";
var valuePartXML = "", trendlinesXML = "";
var xNameArray = [];
if (data['trendlines']) { // ???(??:??,???), ????? : {?:??}
trendlinesXML = "<trendlines> ";
for (var key in data['trendlines']) {
trendlinesXML += "<line startValue='" + key + "' color='" + data['trendlines'][key].replace('#', '')
+ "' displayValue='" + key + "' showOnTop='1' />";
}
trendlinesXML += "</trendlines>";
delete data['trendlines'];
}
DataXML += "<categories>"
for (var key in data) {
if (key.length > 0) {
var record = data[key];
for (var xName in record) {
/* xNameArray.indexOf(xName) == -1 && */
if (xName && String(xName).length > 0) {
DataXML += "<category label=\"" + xName + "\"/>"; // x???
xNameArray.push(xName);
}
}
break; // ????, ???????????. (???????)
}
}
DataXML += "</categories>";
for (var key in data) { // ??
if (key.length > 0) {
var record = data[key];
valuePartXML += "<dataset seriesName=\"" + key + "\">";
for (var i = 0; i < xNameArray.length; i++) {
var xName = xNameArray[i];
if (record[xName] && String(record[xName]).length > 0) {
valuePartXML += "<set value=\"" + record[xName] + "\"/>"; // x???
} else if (this.isLineChart == true) {
record[xName] = this.getEstimated(xName, record, xNameArray);
valuePartXML += "<set showValue =\"0\" toolText=\" \" displayValue=\" \" value=\"" + record[xName] + "\"/>"; // x???
}
}
valuePartXML += "</dataset>";
}
}
DataXML += valuePartXML + trendlinesXML;
DataXML += "</chart>"
this.chart.setDataXML(DataXML);
this.chart.show(); // render
},
/** line????????,?????. */
getEstimated : function(xName, record, xNameArray) {
var front = null;
var back = null;
var space = 2;
for (var i = xNameArray.indexOf(xName) - 1; i > -1; i--) {
var currUp = record[xNameArray[i]];
if (currUp != null && String(currUp).length > 0) {
front = Number(currUp);
break;
}
space++;
}
for (var i = xNameArray.indexOf(xName) + 1; i < xNameArray.length; i++) {
var currDown = record[xNameArray[i]];
if (currDown != null && String(currDown).length > 0) {
back = Number(currDown);
break;
}
space++;
}
if (front == null || back == null) {
return null;
} else {
return (back - front) / space + front;
}
}
})
What is the best way to proceed and what are the advantages/disadvantages?
Any help is greatly appreciated and sorry for the rookie question!
Best
/R

Related

Display day with hours in Angularjs

Here are date and time.
Date 2018-05-25T10:35:04.000Z
Expected Output = 3 days 12 hours
I want to display date and time same like as a give above. Currently, I am using moment.js. Is there any way to display like above?
Alternatively to Zvi's suggestion, you could use the AngularJS date filter
Say in your controller you have 2 dates:
app.controller('AppCtrl', function($scope) {
ctrl = this;
ctrl.date1 = new Date("2018-05-22T22:35:04.000Z");
ctrl.date2 = new Date("2018-05-25T10:35:04.000Z");
});
And in HTML, you'd display the difference with the date filter:
{{ctrl.date2 - ctrl.date1 | date:"dd 'days' HH 'hours'"}}
Here's a working JSFiddle example
You can use this moment-precise-range.
Here's full example:
calcDiff = (date : string) => {
let diff_in_string = '';
let original_date = moment(date);
let date_time_now = moment();
let diff_in_object: any = moment-presice.preciseDiffBetweenDates(original_date, date_time_now, true);
if (diff_in_object.days > 0) {
diff_in_string = diff_in_string + diff_in_object.days + ' ';
if (diff_in_object.days === 1) {
diff_in_string += 'Day '
} else {
diff_in_string += 'Days '
}
}
if (diff_in_object.hours > 0) {
if (diff_in_object.days > 0) {
diff_in_string += 'and ' + diff_in_object.hours + ' '
} else {
diff_in_string += diff_in_object.hours + ' '
}
if (diff_in_object.hours === 1) {
diff_in_string += 'Hour '
} else {
diff_in_string += 'Hours '
}
}
diff_in_string += 'ago'
return diff_in_string;
}
You should consider using The HumanizeDuration library (you can check this answer).
It allows you to translate in any language you want the difference between two dates the way you want.
For example :
var yourdate= moment().set({'year': 2018, 'month': 5, 'day': 22});
var today = moment();
var duration = moment.duration(today.diff(yourdate));
var humanized = humanizeDuration(duration, { units: ['d', 'h'], language: language, round: true });
You can also format it with spacers, etc.

React—catch scroll wheel, but ignore scrollbar

I'm trying to create a scroll-in-viewport-height-increments function and I'm realizing that I only want it to apply to the mousewheel.
Suggestions on how to do this?
Extra credit if you can tell me why my handleScroll function repeats over and over after a single scroll action.
FIDDLE:
componentDidMount() {
window.addEventListener('scroll', this.handleScroll)
}
componentWillUnmount() {
window.removeEventListener('scroll', this.handleScroll)
}
handleScroll(e) {
var didScroll;
var delta = 71;
clearTimeout($.data(this, 'scrollTimer'));
$.data(this, 'scrollTimer', setTimeout(() => {
didScroll = true;
if (didScroll) {
var vh = $(window).height();
hasScrolled(vh);
didScroll = false;
}
}, 40));
function hasScrolled(vh) {
var st = $('body').scrollTop();
var scrolldown = st + vh;
var scrollup = st - vh;
if (Math.abs(lastScrollTop - st) <= delta)
return;
if (st > lastScrollTop && st > 70) {
console.log('scrolltop: ' + st + ', viewport height: ' + vh + ', scrolltop DOWN: ' + scrolldown);
$('body').animate({
scrollTop: scrolldown
}, 300, 'swing');
} else {
console.log('scrolltop: ' + st + ', viewport height: ' + vh + ', scrolltop UP: ' + scrollup);
$('body').animate({
scrollTop: scrollup
}, 300, 'swing');
}
lastScrollTop = st;
}
}

multiple markers on same location google maps, so OverlappingMarker

{literal}
<script type="text/javascript">
function TypeaheadCtrl($scope, $http, $compile) {
var firstLoad = true;
var markerClusterer = null;
var oms = null;
$scope.myMarkers = [];
$scope.infoWindow = new google.maps.InfoWindow();
$scope.mapOptions = {
center: new google.maps.LatLng(41.222298, -73.439740),
zoom: 8,
mapTypeId: google.maps.MapTypeId.TERRAIN
};
$scope.getDynamicMin = function(){ $scope.dynamic_min; }
$scope.getDynamicMax = function(){ $scope.dynamic_min; }
$scope.dynamic_value = ($scope.dynamic_max - $scope.dynamic_min)/2;
$scope.SliderCtrlFn = function(vrange) {
$scope.min = (vrange >= 1 && vrange <=3) ? 1 : (vrange >=4 && vrange <=15) ? 18 : (vrange >= 16 && vrange <=25) ? 25 : (vrange >= 26 && vrange <=36) ? 36 : (vrange >= 37 && vrange <=51) ? 45 : 60;
$scope.max = (vrange >= 1 && vrange <=3) ? 130 : (vrange >=4 && vrange <=15) ? 24 : (vrange >= 16 && vrange <=25) ? 35 : (vrange >= 26 && vrange <=36) ? 44 :(vrange >= 37 && vrange <=51) ? 59: 130;
$scope.getcontacts('Age');
}
$scope.Gender_selectAction = function () {
$scope.getcontacts('Gender');
}
$scope.genders = [{value: '1',name: 'Female'}, {value: '2',name: 'Male'}];
$scope.getcontacts = function (fieldname) {
CDname = $scope.cong_dist;
SDname = $scope.senate_dist;
Assembly = $scope.assembly_dist;
Pname = $scope.precinct_name;
Citycode = $scope.city_code;
Gender = $scope.Gender;
Minage = $scope.min;
Maxage = $scope.max;
var dataUrl = {/literal}"{crmURL p='civicrm/contact/mapcontacts/filter/getcontacts' }"{literal};
return $http.get(dataUrl, {
params: {
fieldName:fieldname,
CDname:CDname,
SDname:SDname,
Assembly:Assembly,
Pname:Pname,
Citycode:Citycode,
Gender:Gender,
Minage:Minage,
Maxage:Maxage,
sensor: false
}
}).then(function(res){
$scope.myMarkers = [];
if(res.data && res.data != "null" && res.data != ""){
var infoWindow=$scope.infoWindow;
angular.forEach(res.data, function(item){
marker = $scope.createmarker(item,infoWindow);
var oms = new OverlappingMarkerSpiderfier($scope.nggMap);
$scope.myMarkers.push(marker);
});
$scope.infoWindow.close();
var markerCluster = new MarkerClusterer($scope.nggMap, $scope.myMarkers);
}
return $scope;
});
}
$scope.createmarker = function(item,infoWindow){
var point = new google.maps.LatLng(item.geo_code_1,item.geo_code_2);
var marker = new google.maps.Marker({
map: $scope.nggMap,
position: point,
contactid: item.contact_id,
title: item.display_name ,
zIndex: google.maps.Marker.MAX_ZINDEX + 5
}); //,animation: google.maps.Animation.DROP
marker.content = '<div class="infoWindowContent">' + item.display_name + '</div>';
google.maps.event.addListener(marker, 'click', function(){
infoWindow.setContent('<h2>' + marker.content + '</h2>');
infoWindow.open($scope.nggMap, marker);
});
oms.addMarker(marker);
return marker;
}
ms.addListener('click', function(marker, event) {
$scope.infoWindow.open($scope.nggMap, marker);
});
}
</script>
{/literal}
so i want to use OverlappingMarkerSpiderfier anybody can plz help me how to use it??
i have already used library in my html.
and put OverlappingMarkerSpiderfier code i am getting error so plz can anybody help me to solve this issue.
Try to Use Like
for (var i = 0; i < window.mapData.length; i ++) {
var datum = window.mapData[i];
var loc = new gm.LatLng(datum.lat, datum.lon);
var marker = new gm.Marker({
position: loc,
title: datum.h,
map: map
});
marker.desc = datum.d;
oms.addMarker(marker); // <-- here
}
You will find the details doc. and code regarding this refer this link

Is there a extJS tri state/three state checkbox?

Looking for a checkbox that can hold three states.
Use:
True, False, Unknown.
Expected behavior:
[x], [ ], [~]
Anyone know of anything?
Ext 3.* Tri-state from this website
Ext 6.2.1
This code exerpt is from sencha forums
{
name: 'optionalChange',
fieldLabel: 'Optional change',
xtype: 'tri-checkbox',
value: 'null'
},
.x-checkbox-null .x-form-checkbox-default {
border: 1px inset #a0a0a0;
background: lightgrey;
box-shadow: 0 0 0 1px hsl(0, 0%, 80%);
}
/**
* Tri-state Checkbox.
* Author: ontho & nux
* Source: https://www.sencha.com/forum/showthread.php?138664-Ext.ux.form.TriCheckbox&p=619810
*
* Note! You must add `x-checkbox-null` style for yourself.
* This might work for classic theme:
.x-checkbox-null .x-form-checkbox-default {
background-position: -39px -26px;
}
*
*/
Ext.define('Ext.ux.form.TriCheckbox', {
extend: 'Ext.form.field.Checkbox',
alias: ['widget.xtricheckbox', "widget.tri-checkbox"],
triState: true, // triState can dynamically be disabled using enableTriState
values: ['null', '0', '1'], // The values which are toggled through
checkedClasses: ['x-checkbox-null', '', Ext.baseCSSPrefix + 'form-cb-checked'], // The classes used for the different states
currentCheck: 0, // internal use: which state we are in?
getSubmitValue: function()
{
return this.value;
},
getRawValue: function()
{
return this.value;
},
getValue: function()
{
return this.value;
},
initValue: function()
{
var me = this;
me.originalValue = me.lastValue = me.value;
me.suspendCheckChange++;
me.setValue(me.value);
me.suspendCheckChange--;
},
setRawValue: function(v)
{
var me = this;
if (v === false || v == 0)
v = '0';
if (v === true || v == 1)
v = '1';
if (v == null || v == '' || v === undefined)
{
if (!this.triState)
v = '0';
else
v = 'null';
}
var oldCheck = me.currentCheck;
me.currentCheck = me.getCheckIndex(v);
me.value = me.rawValue = me.values[me.currentCheck];
// Update classes
var inputEl = me.inputEl;
if (inputEl)
{
inputEl.dom.setAttribute('aria-checked', me.value == '1' ? true : false);
}
me['removeCls'](me.checkedClasses)
me['addCls'](me.checkedClasses[this.currentCheck]);
},
// this is a defaul Checkbox style setter we need to override to remove defult behaviour
updateCheckedCls: function(checked) {
},
// Returns the index from a value to a member of me.values
getCheckIndex: function(value)
{
for (var i = 0; i < this.values.length; i++)
{
if (value === this.values[i])
{
return i;
}
}
return 0;
},
// Handels a click on the checkbox
listeners: {
afterrender: function()
{
var me = this;
this.el.dom.onclick = function(){
me.toggle();
return false;
};
}
},
// Switches to the next checkbox-state
toggle: function()
{
var me = this;
if (!me.disabled && !me.readOnly)
{
var check = me.currentCheck;
check++;
if (check >= me.values.length) {
check = (me.triState == false) ? 1 : 0;
}
this.setValue(me.values[check]);
}
},
// Enables/Disables tristate-handling at runtime (enableTriState(false) gives a 'normal' checkbox)
enableTriState: function(bTriState)
{
if (bTriState == undefined)
bTriState = true;
this.triState = bTriState;
if (!this.triState)
{
this.setValue(this.value);
}
},
// Toggles tristate-handling ar runtime
toggleTriState: function()
{
this.enableTriState(!this.triState);
}
});

directive function calling multiple times in angularjs

I have created directive in anguular js to resize image in angularjs.
Here is the code of directive :
app.directive('resize1', function ($window) {
return {
restrict: 'A',
replace: true,
scope: {
params: '&',
path: '=',
siteurl: '='
},
link: function($scope, element, attrs) {
$scope.resizeImage = function() {
var size = 0;
var width = angular.element($window).width();
src = $(element).attr('src');
if (src != null || src != '') {
var url = parse_url(src).query;
var path = parse_url(src).path;
var str = url.split('&');
var link = '?';
$.each(str, function(index, value) {
pair = value.split('=');
if (pair[0] != 'h' && pair[0] != 'w') {
link = link + value + '&';
}
});
if (width >= 960) {
size = $scope.$eval($scope.params).gt960;
newWidth = size.w;
newHeight = size.h;
} else if (width < 960 && width >= 480) {
size = $scope.$eval($scope.params).bt480960;
newWidth = size.w;
newHeight = size.h;
} else {
size = $scope.$eval($scope.params).lt480;
newWidth = size.w;
newHeight = size.h;
}
link = link + 'h=' + newHeight + '&w=' + newWidth;
$(element).attr('src', path + link);
$(element).attr('ng-src', path + link);
$(element).closest('div.spinner').css({
'height' : newHeight,
'width' : newWidth,
'margin' : '0px auto'
});
}
};
angular.element($window).bind('resize', function() {
$scope.resizeImage();
});
$scope.$watch('path', function (){
//alert('df');
$scope.resizeImage();
});
}
}
});
and my html is :
<div class="list-view" ng-hide="productDetail == null">
<div class="list-view-img">
<div class="spinner">
<img resize1
ng-src="{{siteurl}}thumbnails/index?file={{path}}&h=200&w=200"
params="{lt480: {h: 300,w: 300}, bt480960: {h: 450,w: 450}, gt960: {h: 940,w: 940}}"
path="paths.products.primary_image + productDetail.primary_image"
siteurl="siteUrl"
/>
</div>
</div>
</div>
Now the problem is its working fine but directive function is called 3 times..
Can anybody tell me what can be wrong ? why it is called thrice though i have called it once ?

Resources