gdurniak:
Very strange. The separate “Methods” in Servoy 3 made more sense
Now, when I do a file “search”, and select an item found, I end up in the middle of this “globals” file, with no idea which function I am in
and an even bigger “downside” is that a format error in one global function wipes them all out. Try it. This seems a bug
Best practice is to organize your code in scopes now and use globals as little as possible. A whole bunch of unrelated code in one file = bad. Related code in one scope file = good. Example scope called “FRACTIONS” from https://www.servoyforge.net/projects/fractions:
/**
* Wrapped an open source fractional library for Servoy use.
* Note: this is an early version of ratio.js. (https://github.com/LarryBattle/Ratio.js)
* @author Data Mosaic <http://www.data-mosaic.com/>
*
* @author Larry Battle <http://bateru.com/news/contact-me>
* @license MIT
* @version 1.0
* @date May 08, 2012
* @purpose To provide a function that converts a decimal to a simplified fraction.
* @info <http://bateru.com/news/2012/05/code-of-the-day-javascript-convert-decimal-to-a-simplified-fraction/>
*/
/**
* Highest denominator to attempt to match on
* @type {Number}
* @private
*
* @properties={typeid:35,uuid:"D2D263FE-7078-410E-A130-5DC6427D39D2",variableType:4}
*/
var _fractionPrecision = 64;
/**
* Highest number of decimals
* @type {Number}
* @private
*
* @properties={typeid:35,uuid:"B3D8AC4E-18C4-42EF-A643-26B531D7F733",variableType:4}
*/
var _decimalPrecision = 6;
/**
* Only calculate the fraction array once
* @type {Object}
* @private
*
* @properties={typeid:35,uuid:"DFCD9BB3-AFAF-4299-80F1-30A89B6EF19C",variableType:-4}
*/
var _fractionObject = getFractionObject();
/**
* Get object with all possible fractions
* @private
*
* @properties={typeid:24,uuid:"74B39990-D0A6-44A6-A209-5E2823AF2380"}
*/
function getFractionObject() {
function getKeys(obj) {
var props = [];
for (var prop in obj) {
if (obj.hasOwnProperty(prop)) {
props.push(prop);
}
}
return props;
};
var obj = {
0 : '0',
1 : '1'
},
num = _fractionPrecision,
den = _fractionPrecision + 1,
value;
while (--num) {
while (--den > 1) {
value = (num / den).toFixed(_decimalPrecision);
if (value < 1) {
obj[value] = num + "/" + den;
}
}
den = _fractionPrecision + 1;
}
obj.keys = getKeys(obj);
return obj;
};
/**
* Get the closest number
*
* @param {Number[]} arr
* @param {Number} val
* @return {Number|Boolean}
* @private
*
* @properties={typeid:24,uuid:"F76DF876-15E8-4AD3-949B-22E3C16602E4"}
*/
function getClosestNum(arr, val) {
if (typeof arr !== "object" || !(arr.hasOwnProperty('length')) || isNaN(val)) {
return false;
}
var i = arr.length,
j = i - 1,
minDiff = Math.abs(+val - arr[j]),
diff;
while (i--) {
diff = Math.abs(+val - arr[i]);
if (diff < minDiff) {
minDiff = diff;
j = i;
}
}
return arr[j];
};
/**
* Get a fraction representation from a decimal
*
* @param {Number} dec
* @return {String|Boolean}
*
* @properties={typeid:24,uuid:"9654BA30-4AA4-4C93-BCEF-108F4730E4E0"}
*/
function getFractionFromDecimal(dec) {
if (isNaN(dec) || !isFinite(dec)) {
return false;
}
if (!/\./.test(dec)) {
return dec;
}
var fracs = _fractionObject,
matches = dec.toString().match(/(\d+)(\.\d+)/),
fraction = fracs[getClosestNum(fracs.keys, Math.abs(+matches[2]))],
sign = ( 0 < dec || (fraction == "0" && Math.abs(dec) < 1) ) ? '' : '-';
if (1 < Math.abs(dec)) {
if (isNaN(fraction)) {
fraction = +matches[1] + " " + fraction;
} else {
fraction = +matches[1] + (+fraction);
}
}
return sign + fraction;
};
/**
* Get a decimal representation from a fraction
*
* @param {String} fraction
* @return {Number|Boolean}
*
* @properties={typeid:24,uuid:"41703256-520A-42B4-84EC-D8813CE6DA77"}
*/
function getDecimalFromFraction(fraction) {
var parts = [],
j,
arr = [];
/**
* @param {Array} parts
* @param {Array} arr
* @return {Number}
*/
function frac(parts,arr) {
function getNumeratorWithSign(top, bottom) {
var sign = (+top * (+bottom || 1)) < 0 ? -1 : 1;
return Math.abs(+top) * sign;
}
parts = parts.split(/\//);
arr[0] = getNumeratorWithSign(parts[0], parts[1]);
arr[1] = Math.abs(+parts[1]);
return arr
}
//nothing
if (!fraction) {
return 0
}
//whole number
else if (fraction == parseInt(fraction)) {
return parseInt(fraction)
}
else if (/\d\s*\//.test(fraction)) {
//mixed number
if (/\d\s+[+\-]?\d/.test(fraction)) {
parts = fraction.match(/(\S+)\s+(\S.*)/);
arr = frac(parts[2],[]);
j = 0 < (parseFloat(parts[1]) * arr[0]) ? 1 : -1;
arr[0] = j * (Math.abs(arr[0]) + Math.abs(parts[1] * arr[1]));
}
//fraction
else {
arr = frac(fraction,arr)
}
return arr[0] / arr[1]
}
}
/**
* Called for performing a conversion between a displayed value and a database value.
*
* @param {String|Number} displayedValue The displayed value.
*
* @return {Number} the database value.
*
* @properties={typeid:24,uuid:"861CC360-A31D-48FC-991E-416A5A7C3941"}
*/
function convertFraction2DB(displayedValue) {
if (typeof displayedValue == 'string') {
return getDecimalFromFraction(displayedValue)
}
}
/**
* Called for performing a conversion between a database value and a displayed value.
*
* @param {Number} databaseValue The database value.
*
* @return {String} the displayed value.
*
* @properties={typeid:24,uuid:"6F37C385-32FF-4B62-A54B-B4E82BF9A5FB"}
*/
function convertDB2Fraction(databaseValue) {
//don't show .0 for whole numbers
if (typeof databaseValue == 'number' && parseInt(databaseValue) == databaseValue) {
return utils.numberFormat(databaseValue,'#')
}
//format the fraction
else if (typeof databaseValue == 'number') {
return getFractionFromDecimal(databaseValue)
}
//shouldn't need this return; needed to break out of loop when called with display instead of database value as input
else {
return databaseValue
}
}
Way better than Servoy 3 once you reorganize things.