Dynamically adjust Textfield width to Content - qooxdoo

Is there a way in Qooxdoo to automatically adjust the width of the qx.ui.form.TextField to fit its Content?
It means if someone types in the Textfield it should grow and vice versa.

Here is an example in the Qooxdoo playground that listen to input's updates, use the canvas to calculate the text's length and adjust the textfield's width.
var tt = new qx.ui.form.TextField();
this.getRoot().add(tt);
tt.addListener("input",function(e){
this.setWidth(parseInt(getTextWidth(e.getData(), "12px Verdana"))+10);
},tt);
function getTextWidth(text, font) {
var canvas = getTextWidth.canvas || (getTextWidth.canvas = document.createElement("canvas"));
var context = canvas.getContext("2d");
context.font = font;
var metrics = context.measureText(text);
return metrics.width;
}

Related

FabricJS object is not selectable/clickable/resizable in top left corner (React + FabricJs)

I have FabricJs canvas. And I have multiple objects outside canvas. When I click on object, it appears in Canvas. I am not doing anything else with this object programmatically.
Here is part of code that add image to Canvas (it is React code):
const { state, setState } = React.useContext(Context);
const { canvas } = state;
...
const handleElementAdd = (event, image) => {
const imageSize = event.target.childNodes[0].getBoundingClientRect();
const imageUrl = `/storage/${image.src}`;
new fabric.Image.fromURL(imageUrl, img => {
var scale = 1;
if (img.width > 100) {
scale = 100/img.width;
}
var oImg = img.set({
left: state.width / 2 - img.width * scale,
top: state.height / 2 - img.height * scale,
angle: 0})
.scale(scale);
canvas.add(oImg).renderAll.bind(canvas);
canvas.setActiveObject(oImg);
});
};
...
<div
key={img.name}
onClick={(e) => handleElementAdd(e, img)}
className={buttonClass}
>
It appears, I can drag and drop, resize, select it. However, when my object is placed in top left corner of canvas, it is not clickable, resizable etc. I can select larger area and then object is selected, but it doesn't respond to any events like resize, select etc.
Not sure where to look at.
I read that if coordinates are changed programmatically object.setCoord() to object can help, but in this case I do not understand where to put it.
You have to put (call) object.setCoords() each time you have modified the object, or moved the object. So, you can call it on mouseUp event of the canvas.
You can write a function naming "moveObject" in which you get the object you are trying to move/moved/updated. And then just selectedObject.setCoords().
Then call that function inside canvas.on('selection:updated', e => {----})

Upload Image Width and Height get in react

I am new to React and react hook I want to upload an image from anywhere but I want to know the width and height of a select image before storing it in the database. I want to store the original image metadata width and height. anyone can help me
One solution can be to use FileReader, something like this should work:
const image = new Image();
let fr = new FileReader();
fr.onload = function() {
if (fr !== null && typeof fr.result == "string") {
image.src = fr.result;
}
};
fr.readAsDataURL(inputFile);
image.onload = async function() {
const width = image.width;
};
You can take a look here: https://github.com/toncic/Image-Classification/blob/master/src/Components/ImageClassification.tsx#L45

How to set Amcharts 4 scrollbar color?

I am trying to set scrollbar color in Amcharts, but none of the options specified on Amcharts site has worked.
I am using "#amcharts/amcharts4": "^4.2.2" in react app.
I have tried many options which are mentioned below. None of them are working.
chart.scrollbarX = new am4core.Scrollbar();
chart.scrollbarX.fill = "#017acd";
chart.scrollbarX.setFill(new am4core.color("#017acd"));
chart.scrollbarX.setStroke(new am4core.color("#017acd"));
chart.scrollbarX.stroke = "#017acd"; //this sets the border line color of
scrollbar.
Thanks for the help.
A scrollbar has a background, a thumb, a startGrip and an endGrip. Each of them can be styled individually by :
chart.scrollbarX.background.fill = am4core.color("#017acd");
chart.scrollbarX.thumb.background.fill = am4core.color("#017acd");
chart.scrollbarX.startGrip.background.fill = am4core.color("#017acd");
chart.scrollbarX.endGrip.background.fill = am4core.color("#017acd");
chart.scrollbarX.stroke = am4core.color("#017acd");
You can create different states for all the components to set different colors for hover or press (down).
chart.scrollbarX.thumb.background.states.getKey('hover').properties.fill = am4core.color("#017acd");
chart.scrollbarX.thumb.background.states.getKey('down').properties.fill = am4core.color("#017acd");
I created this code pen to show you a complete example.
If you want to style not a single scrollbar, but all the scrollbars in your app I would suggest creating a custom theme for that.
function am4themes_myTheme(target) {
if (target instanceof am4core.InterfaceColorSet) {
target.setFor("secondaryButton", am4core.color("#6DC0D5"));
target.setFor("secondaryButtonHover", am4core.color("#6DC0D5").lighten(-0.2));
target.setFor("secondaryButtonDown", am4core.color("#6DC0D5").lighten(-0.2));
target.setFor("secondaryButtonActive", am4core.color("#6DC0D5").lighten(-0.2));
target.setFor("secondaryButtonText", am4core.color("#FFFFFF"));
target.setFor("secondaryButtonStroke", am4core.color("#467B88"));
}
if (target instanceof am4core.Scrollbar) {
target.stroke = am4core.color("#017acd");
}
}
am4core.useTheme(am4themes_myTheme);
Here is a code pen showing a theme example.

jsPDF muliple pages with div height - unable to determine the height

I am trying to generate a pdf from html divs with dynamic height and width. Below is the code.
let pages = this.rootDataContainer.nativeElement.getElementsByClassName('pdfpage');
for (let i = 0; i < pages.length; i++) {
this.pdfDoc.addHTML(pages[i], 0, 0, options, () => {
let pxHeight = pages[i].offsetHeight / scaleFactor;
this.pdfDoc.addPage(0, pxHeight);
this.counter = this.counter - 1;
});
}
There are couple of issues I am facing.
As addHTML is async, pages are added to pdf in random way.
height of the pdf page is either getting more or less height.
is there any way to set pdf size and sync the order of pages.
To sync I would use a recursive approach as in:
EDITED:
var pages = document.getElementsByClassName("pdfpage");
var pdfDoc = new jsPDF('p', 'pt', [0, 0]);
pdfDoc.deletePage(1);
pdfDoc.addPage(pages[0].clientWidth, pages[0].clientHeight);
var addDivToPdf = function(pageNr) {
pdfDoc.addHTML(pages[pageNr], 0, 0, {background:"#FFF"}, () => {
if (++pageNr < pages.length) {
//New added DIV dimensions here
pdfDoc.addPage(pages[pageNr].clientWidth, pages[pageNr].clientHeight);
addDivToPdf(pageNr);
} else {
pdfDoc.save("sample-file.pdf");
}
});
};
Notice I haven't use a for loop. This way the next page is added only when the previous is complete.
For the height, I'm not sure, scaleFactor must have the wrong units. It is not really clear if you want all pages to have the same size or you want different sizes to match the DIV height.
UPDATE: To control the widht and height according with the DIVs sizes, I have indicated 'pt' in the pdfDoc constructor:
var pdfDoc = new jsPDF('p', 'pt', [0, 0]);
However the first page appears to have always an standard size, so I have deleted it and added again with the desired size before adding the first DIV. The other pages can follow the normal flow:
pdfDoc.deletePage(1);
pdfDoc.addPage(pages[0].clientWidth, pages[0].clientHeight);
The CodePen is updated:
https://codepen.io/zameb/pen/BdbEVr

How to add legends in Amserial charts

I am using Amcharts in my AngularJS Application to create a simple bar chart.The following is my code in the controller:
let empChart;
let empBarGraph;
let empLine;
const writeemp = data => {
const {
total,
employees,
} = data;
empChart.dataProvider = e;
empChart.write('emp');
empChart.validateData();
};
AmCharts.handleLoad();
var configChart = function () {
empChart = new AmCharts.AmSerialChart();
empChart.categoryField = "state";
empChart.labelRotation = 90;
var yAxis = new AmCharts.ValueAxis();
yAxis.position = "left";
empChart.addValueAxis(yAxis);
empBarGraph = new AmCharts.AmGraph();
empBarGraph.valueField = "count";
empBarGraph.type = "column";
empBarGraph.fillAlphas = 1;
empBarGraph.lineColor = "#f0ab00";
empBarGraph.valueAxis = yAxis;
empChart.addGraph(empBarGraph);
empChart.write('empChart');
$http.get(hostNameService.getHostName()+"/dashboard/employees/statecount")
.then(response => writeemp(response.data));
}
Code in html:
<div class='panel-body'>
<div id="empChart"></div>
</div>
This would return me the values of State on x-axis and count on y-axis. I wanted to filter the chart based on the value of state and was not sure how to create the legends for this chart. could anyone suggest me on how to use legends. I want to create legends for the state value that is being returned.
You can add a legend using the OO-based syntax by creating a legend object through new AmCharts.AmLegend() and adding it to the class by calling the chart's addLegend method:
var legend = new AmCharts.AmLegend();
empChart.addLegend(legend);
If you want the legend to show values upon hovering over a column, you need to add a ChartCursor to your chart:
var cursor = new AmCharts.ChartCursor();
empChart.addChartCursor(cursor);
You can change what the legend displays upon column rollover by setting the valueText property. It allows for the same [shortcodes] used in fields like balloonText and labelText, e.g. legend.valueText = "[[category]]: [[value]]". You can also use set its valueFunction if you need to customize the text it returns dynamically like in your previous questions. All of the properties available in the legend object can be found in the AmLegend API documentation.
Updated:
Legends work off of graph objects only, so there isn't an out of the box method that allows you to represent each column as a legend item that toggles the other columns' visibility unless you're willing to reorganize your dataset and use different graph objects for each state. A workaround for this is to use the the legend's custom data array and add some event handling so that clicking on the custom data items adds/removes a toggle by unsetting your count valueField in the dataProvider.
The following annotated code accomplishes what you're trying to do:
//create the legend but disable it until the dataProvider is populated,
//since you're retrieving your data using AJAX
var legend = new AmCharts.AmLegend();
legend.enabled = false;
chart.addLegend(legend);
chart.toggleLegend = false;
// Callback that handles clicks on the custom data entry markers and labels
var handleLegendClick = function(legendEvent) {
//Set a custom flag so that the dataUpdated event doesn't fire infinitely
legendEvent.chart.toggleLegend = true;
// The following toggles the markers on and off.
// The only way to "hide" a column is to unset the valueField at the data index,
// so a temporary "storedCount" property is added to the dataProvider that stores the
// original value so that the value can be restored when the legend marker is toggled
// back on
if (undefined !== legendEvent.dataItem.hidden && legendEvent.dataItem.hidden) {
legendEvent.dataItem.hidden = false;
legendEvent.chart.dataProvider[legendEvent.dataItem.stateIdx].count = legendEvent.chart.dataProvider[legendEvent.dataItem.stateIdx].storedCount; //restore the value
} else {
// toggle the marker off
legendEvent.dataItem.hidden = true;
legendEvent.chart.dataProvider[legendEvent.dataItem.stateIdx].storedCount = legendEvent.chart.dataProvider[legendEvent.dataItem.stateIdx].count; //store the value
legendEvent.chart.dataProvider[legendEvent.dataItem.stateIdx].count = undefined; //set to undefined to hide the column
}
legendEvent.chart.validateData(); //redraw the chart
}
chart.addListener('dataUpdated', function(e) {
var legendDataItems; //used to store the legend's custom data array.
if (e.chart.toggleLegend === true) {
//is the user toggling a legend marker? stop here as the dataProvider will get updated in handleLegendClick
e.chart.toggleLegend = false;
return;
}
// if we're at this point, the data provider was updated.
// reconstruct the data array.
// initialize by grabbing the state, setting a color and stoing the index
// for toggline the columns later
legendDataItems = e.chart.dataProvider.map(function(dataElement, idx) {
return {
'title': dataElement.state,
'color': graph.lineColor,
'stateIdx': idx //used in toggling
}
});
// if the legend is not enabled, then we're setting this up for the first time.
// turn it on and attach the event handlers
if (e.chart.legend.enabled === false) {
e.chart.legend.enabled = true;
e.chart.legend.switchable = true;
e.chart.legend.addListener('clickMarker', handleLegendClick);
e.chart.legend.addListener('clickLabel', handleLegendClick);
}
// update the legend custom data and redraw the chart
e.chart.legend.data = legendDataItems;
e.chart.validateNow();
});
Here's a fiddle that illustrates this: http://jsfiddle.net/g254sdq5/1/

Resources