Extjs 4: how to change progressbar colour dynamically? - extjs

Question Answer below
Hello I'm looking a simple way to change the colour of a progress bar, what I'm trying to do with it, would look like this:
function (progressBar, value) {
if (value < 40) {
progressBar.setColor('red');
} else if (value >= 40 && value <= 80) {
progressBar.setColor('yellow');
} else {
progressBar.setColor('green');
}
}
Then some kind of way to change the colour through the style with the method progressbar already have, setUI, or other kind of way that it could work would be great as well.
Thanks.
Solution
I found the way to do it, here it is, I create a custom progress bar, where I use the listener update, then this one is going to receive the actual value of the progress bar, and the bar itself, I take the obj and find the styles of the progress bar, where I modify backgroundColor and the borderRightColor with the hex color I want and set the backgroundImage to and empty URL then it will allow the backgroundcolor to show up.
Also I create the option to send a default color.
Here is the code:
Ext.define("progressBarCustom", {
extend: 'Ext.ProgressBar',
alias: 'widget.progressBarCustom',
max: null,
ave: null,
min: null,
color: null,
initComponent: function () {
var me = this;
me.width = 300;
me.margin = '5 5 0 5';
me.callParent(arguments);
},
listeners: {
update: function (obj, val) {
if (this.max != null && this.ave != null && this.min != null) {
if (val * 100 <= this.min) {
obj.getEl().child(".x-progress-bar", true).style.backgroundColor = "#FF0000";
obj.getEl().child(".x-progress-bar", true).style.borderRightColor = "#FF0000";
obj.getEl().child(".x-progress-bar", true).style.backgroundImage = "url('')";
} else if (val * 100 <= this.ave) {
obj.getEl().child(".x-progress-bar", true).style.backgroundColor = "#FFFF00";
obj.getEl().child(".x-progress-bar", true).style.borderRightColor = "#FFFF00";
obj.getEl().child(".x-progress-bar", true).style.backgroundImage = "url('')";
} else {
obj.getEl().child(".x-progress-bar", true).style.backgroundColor = "#009900";
obj.getEl().child(".x-progress-bar", true).style.borderRightColor = "#009900";
obj.getEl().child(".x-progress-bar", true).style.backgroundImage = "url('')";
}
} else if (this.color != null) {
obj.getEl().child(".x-progress-bar", true).style.backgroundColor = this.color;
obj.getEl().child(".x-progress-bar", true).style.borderRightColor = this.color;
obj.getEl().child(".x-progress-bar", true).style.backgroundImage = "url('')";
}
}
}
});
Then if you are going to create a new progressbar with the color changes here is the code:
Ext.create('progressBarCustom', {
min : 0.20,
ave : 0.60,
max : 0.80
});
or just with a default color:
Ext.create('progressBarCustom', {
color : "#4D0099"
});
Any suggestion would be received, thanks :).

I would suggest adding a listener that calls your function on the move event as this appears to contain the positions you need. Documentation link.
For the setColor aspect I believe you want to set the components style elements. Documentation link. Hope that helps.

Related

Extjs - drag drop restriction

How do I restrict the drag operation not exceeding certain boundary. Is there any config in extjs (version 3), I saw that, Ext.dd.DragZone class is used. But Im not sure what is the usability. I saw a method dropNotAllowed. Is that the method, that has to be used? if so, how should I use that? Please provide some examples.
Im looking for something similar to (jquery UI's draggable containment property)
http://docs.sencha.com/extjs/3.4.0/#!/api/Ext.dd.DragZone-cfg-dropNotAllowed
I tried using the set X and Y constraints, but it did not work-out:
abc.prototype.initDrag = function(v) {
v.dragZoneobj = new Ext.dd.DragZone(v.getEl(), {
getDragData : function(e) {
var sourceEl = e.getTarget(v.itemSelector, 10);
// sourceEl.setXConstraint( 0, 10 );
var t = e.getTarget();
var rowIndex = abc.grid.getView().findRowIndex(t);
var columnIndex = abc.grid.getView().findCellIndex(t);
if ((rowIndex !== false) && (columnIndex !== false)) {
if (sourceEl) {
abc.isDragged = true;
abc.scriptGrid.isDraggableForObject = false;
abc.scriptGrid.dragRowIndex = false;
d = sourceEl.cloneNode(true);
d.id = Ext.id();
d.textContent = sourceEl.innerHTML;
// d.setXConstraint( 0, 10 );
// d.setYConstraint( 0, 10 );
return {
ddel : d,
sourceEl : d,
sourceStore : v.store
}
}
}
},
getRepairXY : function() {
return this.dragData.repairXY;
},
});
}
Both are commented in the above code. The above code is initiated when the panel is rendered.
edit:
How these setX and setYcontraints have to be used?
By default, the element can be dragged any place on the screen. In the doc there are two methods setXConstraint( iLeft, iRight, iTickSize) and setYConstraint( iUp, iDown, iTickSize )
These two methods is used to set to limit the vertical travel and horizental travel of the element.

Angular - Delaying forEach

I have a problem. I am trying to create an animation, changing the color of several layers with a timeout between painted.
$scope.StartMovementsAnimation = function()
{
angular.forEach($scope.GameMovements, function(movement){
if (movement == "Green")
{
$scope.Green = true;
}
else (movement == "Orange")
{
$scope.Orange = true;
}
});
}
The problem I have is that I do not know how to stop or delay the flow loop. I'm pretty lost. I tried with $ timeout, sleep etc but does not work.
Any solution?
thanks
Don't use forEach. Use $timeout to repeat as many as the number of items in your GameMovements array.
Take a look at the following example. It is going to change className field from orange to green and vice versa till the variable left's value reaches 0.
$scope.className = "orange";
$scope.count = 0;
$scope.startAnimation = function() {
var left = 10
var ticker = function() {
if (left % 2 === 0)
$scope.className = 'orange'
else
$scope.className = 'green'
left -= 1
if (left > 0) {
$timeout(ticker, 1000)
}
}
$timeout(ticker, 1000)
}

Ext JS EditorGridPanel - How to split cell to show multiple rows

In Ext.grid.EditorGridPanel table how to split a cell to have two or three rows?
Like the below image
I managed to do a kind of rowspan instead of row splitting. IMO it's easier and it looks the same as grid on attached image. Example code:
var grid = new Ext.grid.EditorGridPanel({
[...],
// hook up events
initComponent: function () {
Ext.grid.GridPanel.prototype.initComponent.call(this);
this.getView().on('refresh', this.updateRowSpan, this);
this.getView().on('rowupdated', this.updateRowSpan, this);
},
onLayout : function(vw, vh) {
this.updateRowSpan();
},
// set span on rows
updateRowSpan: function() {
var columns = this.getColumnModel().config,
view = this.getView(),
store = this.getStore(),
rowCount = store.getCount(),
column = columns[0], // put propert column index here
dataIndex = column.dataIndex,
spanCell = null,
spanCount = null;
spanValue = null;
for (var row = 0; row < rowCount; ++row) {
var cell = view.getCell(row, 0),
record = store.getAt(row),
value = record.get(dataIndex);
if (spanValue != value) {
if (spanCell !== null) {
this.setSpan(Ext.get(spanCell), spanCount);
}
spanCell = cell;
spanCount = 1;
spanValue = value;
} else {
spanCount++;
}
}
if (spanCell !== null) {
this.setSpan(Ext.get(spanCell), spanCount);
}
},
// set actual span on row
setSpan: function(cell, count) {
var view = this.getView(),
innerCell = Ext.get(cell.down('*')),
height = cell.getHeight(),
width = cell.getWidth();
cell.setStyle('position', 'relative');
if (count == 1) {
innerCell.setStyle('position', '');
innerCell.setStyle('height', '');
innerCell.setStyle('height', '');
} else {
innerCell.setStyle('position', 'absolute');
innerCell.setStyle('height', (height * count - cell.getPadding('tb') - innerCell.getPadding('tb')) + 'px');
innerCell.setStyle('width', (width - cell.getPadding('lr') - innerCell.getPadding('lr')) + 'px');
}
}
});
This code changes style of .x-grid3-cell-inner by applying position: absolute and big enough size to cover rows below. Notice that you must also apply some opaque background to make it work. Working sample: http://jsfiddle.net/RpxZ5/8/
I first wrote code for Ext JS 4, if you interested, here is working sample: http://jsfiddle.net/wQSQM/3/

Continuous Looping Page (Not Infinite Scroll)

I'm looking for resources that create scrolling functions like the ones found on these sites:
Outpost Journal
Unfold
Once the scroll bar hits the bottom of the page, I want it to loop back to the top.
I'm familiar with with the infinite scroll, and this is not what I want. I've also found scripts that will write/add the same content to the bottom of the page, but none that loop back to the top of the page.
Try this:
$('document').ready(function() {
$(document).scroll(function(){
if(document.documentElement.clientHeight +
$(document).scrollTop() >= document.body.offsetHeight )$(document).scrollTop(0);
});
});
if you want infinite scroll in both directions use
if (document.documentElement.clientHeight + $(window).scrollTop() >= $(document).height()) {
$(document).scrollTop(0)
} else if ($(window).scrollTop() < 0) {
$(document).scrollTop($(document).height())
}
(I know it's a late reply but it still helps users like me who just google stuff like this)
Here a solution that makes a duplicate of the body so the bottom and the top can be seen at the same time at a certain point so the transition is smoother.
$('document').ready(function() {
// We need to duplicate the whole body of the website so if you scroll down you can see both the bottom and the top at the same time. Before we do this we need to know the original height of the website.
var origDocHeight = document.body.offsetHeight;
// now we know the height we can duplicate the body
$("body").contents().clone().appendTo("body");
$(document).scroll(function(){ // detect scrolling
var scrollWindowPos = $(document).scrollTop(); // store how far we have scrolled
if(scrollWindowPos >= origDocHeight ) { // if we scrolled further then the original doc height
$(document).scrollTop(0); // then scroll to the top
}
});
});
mrida's answer was causing my browser to not be able to scroll, here is a modified version that worked for me:
$('document').ready(function() {
$(document).scroll(function(){
if (document.documentElement.clientHeight + $(window).scrollTop() >= $(document).height()) {
$(document).scrollTop(0);
}
});
});
Forked from #clankill3r's answer, create two copy of body, prepend and append to the original body, then you can scroll the page in two direction endless.
$('document').ready(function() {
var origDocHeight = document.body.offsetHeight;
var clone=$("body").contents().clone();
clone.appendTo("body");
clone.prependTo("body");
$(document).scroll(function(){
var scrollWindowPos = $(document).scrollTop();
if(scrollWindowPos >= origDocHeight ) {
$(document).scrollTop(0);
}
if(scrollWindowPos <= 0 ) {
$(document).scrollTop(origDocHeight);
}
});
});
Adding loop scroll backwards, upgrading #clankill3r answer. It should be something like this.
$('document').ready(function() {
// We need to duplicate the whole body of the website so if you scroll down you can see both the bottom and the top at the same time. Before we do this we need to know the original height of the website.
var origDocHeight = document.body.offsetHeight;
// now we know the height we can duplicate the body
$("body").contents().clone().appendTo("body");
$(document).scroll(function(){ // detect scrolling
var scrollWindowPos = $(document).scrollTop(); // store how far we have scrolled
if(scrollWindowPos >= origDocHeight ) { // if we scrolled further then the original doc height
$(document).scrollTop(scrollWindowPos + origDocHeight); // then scroll to the top
} else if (scrollWindowPos == 0) { // if we scrolled backwards
$(document).scrollTop(origDocHeight);
}
});
});
I'm using it horizontally and it's working just fine. Hope someone finds it useful.
Posted a similar question: https://stackoverflow.com/a/65953934/7474712 and found the answer via this pen: https://codepen.io/vincentorback/pen/zxRyzj
Here's the code:
<style>
html,
body {
height: 100%;
overflow: hidden;
}
.infinite {
overflow: auto;
-webkit-overflow-scrolling: touch;
}
.clone {
height: 50vw;
}
</style>
<script>
var doc = window.document,
context = doc.querySelector('.infinite'),
clones = context.querySelectorAll('.clone'),
disableScroll = false,
scrollHeight = 0,
scrollPos = 0,
clonesHeight = 0,
i = 0;
function getScrollPos () {
return (context.pageYOffset || context.scrollTop) - (context.clientTop || 0);
}
function setScrollPos (pos) {
context.scrollTop = pos;
}
function getClonesHeight () {
clonesHeight = 0;
for (i = 0; i < clones.length; i += 1) {
clonesHeight = clonesHeight + clones[i].offsetHeight;
}
return clonesHeight;
}
function reCalc () {
scrollPos = getScrollPos();
scrollHeight = context.scrollHeight;
clonesHeight = getClonesHeight();
if (scrollPos <= 0) {
setScrollPos(1); // Scroll 1 pixel to allow upwards scrolling
}
}
function scrollUpdate () {
if (!disableScroll) {
scrollPos = getScrollPos();
if (clonesHeight + scrollPos >= scrollHeight) {
// Scroll to the top when you’ve reached the bottom
setScrollPos(1); // Scroll down 1 pixel to allow upwards scrolling
disableScroll = true;
} else if (scrollPos <= 0) {
// Scroll to the bottom when you reach the top
setScrollPos(scrollHeight - clonesHeight);
disableScroll = true;
}
}
if (disableScroll) {
// Disable scroll-jumping for a short time to avoid flickering
window.setTimeout(function () {
disableScroll = false;
}, 40);
}
}
function init () {
reCalc();
context.addEventListener('scroll', function () {
window.requestAnimationFrame(scrollUpdate);
}, false);
window.addEventListener('resize', function () {
window.requestAnimationFrame(reCalc);
}, false);
}
if (document.readyState !== 'loading') {
init()
} else {
doc.addEventListener('DOMContentLoaded', init, false)
}
</script>

Changing the colorSet of a series of a Ext.chart.series.Gauge

I'm working with extjs and I dont have a ton of experience with this framework. I have a gauge and I need to change its color after its initialized. In a perfect world, I would change this using
this.myGauge.series.colorSet = ['#fff', '#ddd'];
but colorSet is undefined in this situation.
Creating a new series and assigning it to the chart like so:
this.myGauge.series.add(new Ext.chart.series.Series([{
type: 'gauge',
field: 'value',
donut: 30,
colorSet: ['#aaa', '#ddd']
}]));
This throws an error when it tries to redraw the chart
TypeError: series.drawSeries is not a function
Even though im not explicitly calling drawSeries() anywhere.
What is the best practice for modifying the colorSet of a gauge chart inside an event? The value of the gauge can change, and when it does, I need to update its color (hex codes are just test values).
if (gaugeValue >= 95) {
//Green
this.typicalGauge.series.colorSet = ['#fff', '#ddd'];
} else if (gaugeValue < 95 && gaugeValue >= 85) {
//Yellow
this.typicalGauge.series.colorSet = ['#ccc', '#ddd'];
} else if (gaugeValue < 85) {
//Red
this.typicalGauge.series.colorSet = ['#aaa', '#ddd'];
}
Thanks to Eric Cook I got put on the right path. What I needed to do to change the first item in the colorSet was utilize the index variable passed into the renderer function, like so:
renderer: function (sprite, record, attr, index, store) {
var value = record.get("value");
var color = null;
if (value >= 95) {
color = "#1BE01B";
} else if (value < 85) {
color = "#DEE817";
} else {
color = "#E81717";
}
if (index == 0) {
return Ext.apply(attr, { fill: color });
} else {
return attr;
}
}
The most reliable method I'm aware of is through the renderer function. It's not well documented in my opinion, so here's what it looks like:
renderer: function(sprite, record, attr, index, store){
// You'll probably want to set a breakpoint here just to see what values
// you have to work with. I'm not completely sure myself.
return Ext.apply(attr, {
fill: "#f00" /* This is probably the property you're looking for */
});
}
The Ext JS charts are still pretty buggy in my opinion, so don't be surprised if it doesn't work right off the bat. But that should hopefully get you started.
EDIT: The renderer is called every time the chart redraws. You can get the value from the record like this:
renderer: function(sprite, record, attr, index, store){
var value = record.get("value"),
color;
if (value >= 95) {
color = "#fff";
} else if(value < 85) {
color = "#aaa";
} else {
color = "#ccc";
}
return Ext.apply(attr, {fill: color});
}
I'm not sure if there's a different way to set the actual colorSet, but that's basically what you would do. Then you just redraw the chart and your colors should be changed.

Resources