I have a set of blocks, each have some associated number. I need to make blocks height correspond to this number. For example
As you can see the bigger number - the higher is div.
But its not 1:1 related, right? Otherwise we would not even see the blocks with number "1" or "10". So I'm trying to figure out how to calculate this approximate heights. I know its more like mathematical task.
Update: Also values can be any fractions, including less than 1
Finally, we have a working function that solves this problem.
Suppose we have an array of blocks objects with id and relative number value.
function blockHeights(blocks) {
const MAX_HEIGHT_PX = 500;
let logs = [];
blocks.forEach((block) => {
if (block.value) {
logs.push(Math.log10(block.value));
}
});
const minLog = Math.ceil(Math.min(...logs));
const addition = minLog < 0 ? (1 - minLog) : 0;
const maxLog = Math.ceil(Math.max(...logs)) + addition;
const step = MAX_HEIGHT_PX / maxLog;
let blockHeights = {};
blocks.forEach((block) => {
blockHeights[block.id] = Math.round(step * (Math.log10(block.value) + addition));
});
return blockHeights;
}
----------------------------------------------------------
There is also another solution, which works better in my case: to use the formula from here: https://stats.stackexchange.com/a/281164/266299
and normalize all values to fit between your predefined min and max block height. This way the function is going to look like this:
function blockHeights(blocks) {
const MIN_BLOCK_HEIGHT_PX = 65;
const MAX_BLOCK_HEIGHT_PX = 300;
const maxMinDifference = MAX_BLOCK_HEIGHT_PX - MIN_BLOCK_HEIGHT_PX;
const min = Math.min(...Object.values(blocks));
const max = Math.max(...Object.values(blocks));
blocks.forEach(block=> {
result[block.id] = ((block.value - min) * maxMinDifference / (max - min)) + MIN_BLOCK_HEIGHT_PX;
});
return result;
}
Maybe can loop on each value and check if
if (largestValue > 100) {
percentage = (currentValue / largestValue) * 100
if ( percentage < 5 ) {
BlockXUIHeight = 5
BlockXUIWidth = 5
}
}
Related
My problem is that as far as I know javascript can't handle number format in forms and converts everything to string.
I have a function that lets users select their macronutrient ratio percentages - the sum of carbs, fats, protein have to be sum of 100%.
I store users goal macros as a number in my database and I calculate current percentage totals like this:
const carbsPercentage = ((goalCarbs * 4) / goalCalories) * 100;
const fatsPercentage = ((goalFats * 9) / goalCalories) * 100;
const proteinPercentage = ((goalProtein * 4) / goalCalories) * 100;
Then using React-hook-form watch() method I track users form inputs to recalculate the total percentage:
const watchCarbsPercentage = watch('carbsPercentage');
const watchFatsPercentage = watch('fatsPercentage');
const watchProteinPercentage = watch('proteinPercentage');
const watchCalories = watch('calories');
// gets total percentage based on the sum of the other 3
const getTotalPercentage = () => {
const parsedCarbsPercentage = parseInt(watchCarbsPercentage) || 0;
const parsedFatsPercentage = parseInt(watchFatsPercentage) || 0;
const parsedProteinPercentage = parseInt(watchProteinPercentage) || 0;
const totalPercentage =
parsedCarbsPercentage + parsedFatsPercentage + parsedProteinPercentage;
return totalPercentage;
};
Because of this I get typescript error when I try to use parseInt:
const watchCarbsPercentage: number
Argument of type 'number' is not assignable to parameter of type 'string'.ts(2345)
I thought that typescript would infer that as soon as number is assigned to input it becomes string or am I wrong?
How do I handle this logic correctly?
I'm a beginner, and I'm trying to write a function to calculate the mean of the smallest and highest numbers in any given sequence of numbers. However, I haven't been able to insert the right command inside the parameters of the method. Can you guys help me?
Here's my code:
function midrange () {
let min = Math.min(arguments);
let max = Math.max(arguments);
let mean = (min + max) / 2;
console.log("min:", min);
console.log("max:", max);
return mean;
}
I think you have to pass arguments Value in your Method. If it's not declared Globally
function midrange (...arguments) {
let min = Math.min(...arguments);
let max = Math.max(...arguments);
let mean = (min + max) / 2;
console.log("min:", min);
console.log("max:", max);
console.log(mean)
return mean;
}
midrange(1, 2, 4,7, 1, 2 ,3 ,5)
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/rest_parameters?retiredLocale=uk
You could use Spread syntax (...):
function midrange(...arguments) {
const min = Math.min(...arguments);
console.log(`min: ${min}`);
const max = Math.max(...arguments);
console.log(`max: ${max}`);
return (min + max) / 2;
}
console.log(`midrange: ${midrange(1, 2, 3)}`);
I have a structure of dynamic DOM elements that I'm continuously evaluating with a for loop and a setInterval. While in that interval I sort the array and then change the dom with a JQuery Sort function in order to order my DOM structure on the fly.
The thing is I only want to change the DOM if the sort function is actually changing the order of elements (usually this happens when a new DOM element comes into the structure dynamically), if the sort function runs again over an already sortered array I don't want to do anything with the dom.
I have found A LOT of ways to compare if Arrays are equal but my case is special since i don't really care about the arrays elements / content but I really need to check if those elements are not in the same order so i can change the dom.
setInterval(function () {
//Incoming Chat Structure Variables
var $incomingChatsTable, $incomingChatsRows, $incomingChatTags
$incomingChatsTable= $("div[__jx__id*='incoming_list__list_content_container']")
$incomingChatsRowsContainer=$("div[__jx__id='___$_194__visitor_list__incoming_list__list__content']")
$incomingChatsRows = $("div[class*='renderers_Incoming']")
$incomingChatTags = $( "div[__jx__id*='incoming_list__list__content'] div[class*='renderers_Incoming'] .visitorlist_tags .jx_ui_html_span:last-child .tag").toArray()
$popupTrigger = $("div[jx\\:list\\:rowid]")
//Assigning Priorities Function
function assignPriority(arrayParent) {
for ( var i=0; i <= arrayParent.length; i++) {
var actualRow = $(arrayParent[i])
var minutesInQueue = $(actualRow).find('.time_cell').text().substr(0,2)
var priorityVal = parseInt(minutesInQueue)
var actualRowTags = $( actualRow ).find('.tag').toArray()
$(actualRow).addClass('priorityRow')
for (var k=0; k <= actualRowTags.length; k++) {
let normalHolderTag = $(actualRowTags[k]).text().toLowerCase()
if (normalHolderTag === 'vip') {
priorityVal += 30
$(actualRow).attr('data-priority', priorityVal)
} else if ( normalHolderTag === 'rg' ) {
priorityVal += 20
$(actualRow).attr('data-priority', priorityVal)
} else if ( normalHolderTag === 'accountclosure' ) {
priorityVal += 10
$(actualRow).attr('data-priority', priorityVal)
} else {
$(actualRow).attr('data-priority', priorityVal)
}
//$(actualRow).find('.numbers_cell').text(priorityVal)
}
}
}
//Sorting Incoming Chats By Priority
function orderByPriority(container) {
myArray = container.find('.priorityRow')
var changed = false
myArray.sort(function(a,b){
contentA = parseInt( $(a).data('priority') )
contentB = parseInt( $(b).data('priority') )
if ( (contentB - contentA) * ( myArray.indexOf(b) - myArray.indexOf(a) ) > 0 ){
changed = true
}
return (contentB - contentA)
})
if(changed) {
$(sortedArray).prependTo( container )
} else{
console.log('No need To Sort')
}
}
setInterval(function () {
assignPriority( $incomingChatsRows )
orderByPriority( $incomingChatsRowsContainer )
}, 500)
}, 1000)
UPDATE:
myArray is now a global variable, I have added an IF statement evaluating the sort function result and multiplying that result by the a, b indexes. If that's greater than 0 then i change the value of my "changed" variable to "true" BUT I'm getting a "myArray.indexOf is not a function" error.
You can add a line of code in your orderByPriority sort function which sets a variable to true only if it actually changes something:
function orderByPriority(container) {
var myArray = container.find('.priorityRow')
var changed = false
myArray.sort(function(a,b){
contentA = parseInt( $(a).data('priority') )
contentB = parseInt( $(b).data('priority') )
if((contentB - contentA)*(myArray.index(b)-myArray.index(a))>0){
//check if these have the same sign, i.e. something has changed
changed = true;
}
return (contentB - contentA)
})
if(changed){}//do something to modify DOM
}
The sort function has three possible outputs which will determine whether the two inputs need to be sorted:
Greater than 0: sort a to an index greater than b
Less than 0: sort b to an index greater than a
Equal to 0: don't change the order
The possible conditions which will result in a change being made are therefore:
Output greater than 0 and the index of a is currently less than the index of b
Output less than 0 and the index of a is currently greater than the index of b
We can represent the difference between the two indexes as index(b)-index(a). If the index of a is currently less than the index of b, this value will be positive. Otherwise, the value will be negative.
We can thus see that the above conditions are really saying:
if output and index(b)-index(a) have the same sign, something needs to be changed.
We can check if they have the same sign by multiplying them by eachother and testing if the result is greater than 0. This means that something has changed, so inside the if condition we set changed to true
Hi is there a way to call the function that they use in autoHeight of Column Definitions? I have a function that Expand and Collapse the row based on the content of one column which is remarks. On the initial load the row height is fix for 2 text lines only. And when I click the Expand the row will expand depending on the remarks column content. Their autoHeight is working on initial load to expand the row base on the content but I do not need it on initial load. When I try to update it upon clicking Expand button then calling the resetRowHeights nothing happens. I have a temporary solution which I compute the length of the text, etc. It works on normal scenario but the problem is if they change the width of the column into smaller then expand. I try to get the ratio of text to column to dynamically compute it but the computation failed.
Below is my current code for computing the rows.
expandView() {
this.isExpand = true;
this.gridApi.forEachNode((rowNode: RowNode) => {
let ulRemarksTotalRowHeight = 0;
let customerRemarksTotalRowHeight = 0;
let ulRemarksList = [];
let customerRemarksList = [];
const ulRemarks = rowNode.data.map_ul_remarks;
const customerRemarks = rowNode.data.map_cust_remarks;
if (ulRemarks) {
ulRemarksList = rowNode.data.map_ul_remarks.split('\n');
}
if (customerRemarks) {
customerRemarksList = rowNode.data.map_cust_remarks.split('\n');
}
if (ulRemarksList) {
for (let i = 0; i < ulRemarksList.length; i++) {
const display = ulRemarksList[i];
// 28 - Default height value(in px) of one row in ag-Grid;
// 19 - Maximum text length for one row in ag-Grid(Initial Load/Without Resizing the Column of UL and Customer Remarks);
const ulRemarksHeight = Math.ceil(display.length / 19) * 28;
ulRemarksTotalRowHeight += ulRemarksHeight;
}
}
if (customerRemarksList) {
for (let i = 0; i < customerRemarksList.length; i++) {
const display = customerRemarksList[i];
// 28 - Default height value(in px) of one row in ag-Grid;
// 19 - Maximum text length for one row in ag-Grid(Initial Load/Without Resizing the Column of UL and Customer Remarks);
const customerRemarksHeight = Math.ceil(display.length / 19) * 28;
customerRemarksTotalRowHeight += customerRemarksHeight;
}
}
const largestHeight = Math.max(ulRemarksTotalRowHeight, customerRemarksTotalRowHeight);
if (largestHeight !== 0 && largestHeight > 56) {
rowNode.setRowHeight(largestHeight);
} else {
// 2 rows = 56px;
rowNode.setRowHeight(56);
}
});
this.gridApi.onRowHeightChanged();
}
want to calculate square root of given input so i used this code
var no1:Number = 2;
var no2:Number; //input for calculation
var total:Number;
total=Math.pow(no2,(1/no1));
its working , but i faced problem such as:-
if i give
no2 = 25;
then it shows
total=4.9999999
to overcome this problem i used below code
total=Math.ceil(Math.pow(no2,(1/no1)));
but its okey for 25 .
total = 5
problem was if i give 21,22,23,24
for all this input it shows 5
so is there any other solutions ???
If you want to take the nth root. You can feed the output of your function into arbitrary rounding function like this:
/**
* Rounds input number to specified number of decimal places. For example
* round(4.568, 2) will return 4.57, and round(4.99, 2) will return 5.
*/
function round(num:Number, toDecimalPlaces:uint) {
var factor:uint = Math.pow(10, toDecimalPlaces);
return Math.round(num * factor) / factor;
}
/**
* Returns nth root to two decimal places.
*/
function nthRoot(n:uint, num:Number) {
return round(Math.pow(num, (1 / n)), 2);
}
There's a function for that.
var total:Number = Math.sqrt(no2);
my actual code was like this
var str:String=view.numDisplay.text;//input string
var power:Number = Number(inString.charAt(inString.indexOf('√') - 1));//to get the value before √ i.e no1
var no1:Number;
var no2:Number;
var total:Number;
if(power)
no1=v;
else
no1=2;
no2=getSubTerm();//method to find no2 it returns the number for calculation
total=Math.ceil(Math.pow(no2,(1/no1)));