Formatting text with tabs or spaces - javascript

I have object like this:
{
Name: "John"
Location: "Unknown"
Type: "Unknown"
Status: "Unknown"
Phone_number: "Unknown"
}
Need to format it like this (with tabs or spaces):
Name: John // three tabs
Location: Unknown // two tabs
Type: Unknown // three tabs
Status: Unknown // three tabs
Phone_number: Unknown // one tab
Java and Perl has this functionality in printf, but how to do this in javascript?

Ok. Found here:
/**
* object.padding(number, string)
* Transform the string object to string of the actual width filling by the padding character (by default ' ')
* Negative value of width means left padding, and positive value means right one
*
* #param number Width of string
* #param string Padding chacracter (by default, ' ')
* #return string
* #access public
*/
String.prototype.padding = function(n, c)
{
var val = this.valueOf();
if ( Math.abs(n) <= val.length ) {
return val;
}
var m = Math.max((Math.abs(n) - this.length) || 0, 0);
var pad = Array(m + 1).join(String(c || ' ').charAt(0));
// var pad = String(c || ' ').charAt(0).repeat(Math.abs(n) - this.length);
return (n < 0) ? pad + val : val + pad;
// return (n < 0) ? val + pad : pad + val;
};
This not works with tabs, but works with spaces exactly how I describe in question.
For my example code will be:
$.each(myObj, function(myKey, myVal) {
myOut += myKey.padding(20) + " = " + myVal + "\r\n";
});
Output will be:
Name = John
Location = Unknown
Type = Unknown
Status = Unknown
Phone_number = Unknown

The String.prototype.padEnd(targetLength, padString) method will do the job, it is documented here.
The padString parameter is set to a single-space string if omitted.
Example:
console.log(` ${'Player'.padEnd(19)} ` +
`${'MATCH'.padEnd(8) } ` +
`${'SCORE'.padEnd(8) } `
);
for (const player of this.players) {
console.log(` - ${player.name.padEnd(20)} ` +
`${player.matches.length.toString().padEnd(8) } ` +
`${player.score.toString().padEnd(8) } `
);
}
Result:
Player MATCH SCORE
- Bradly 5 15
- Sam 4 9
- Dew 3 5

EDIT You can add more tabs by using '\t'. Each '\t' means one tab, so in the console.log you can use more console.log(prop + ":\t\t\t" + obj[prop]);
Pass your object to this function (this works for any object):
function printObject(obj)
for(var prop in obj){
if (obj.hasOwnProperty(prop)) {
console.log(prop + ":\t" + obj[prop]);
}
}
You can also get a pretty similar output (but with quotes) by using
JSON.stringify(obj, null, 2);
This will basically print your objects in jason format and will use the last argument (the 2) as the number of separator spaces.

Related

Trying to convert users message into hex from decimal using Discord bot

Ok so I have this
Commands.hex = {
name: 'hex',
help: "I'll convert your steamid for you",
timeout: 10,
level: 0,
fn: function (msg, suffix) {
msg.reply('Steam64').then((m) => {
m.edit('<#' + msg.author.id + '>, Steam ID Converted: ' + suffix.toString(16)).slice(-2).toUpperCase()
})
}
}
i'm trying to get it to do what this website does
http://www.binaryhexconverter.com/decimal-to-hex-converter
I'm just trying to get it to convert for my discord bot, thank you!
As it turns out your value: 76561198262006743 is much greater than Number.MAX_SAFE_VALUE, which is (2^53 -1). This will lead to undefined behavior when trying to do arithmetic.
For example, on Google Chrome when typing just the number into the console and pressing enter, that value became 76561198262006740 (note the 3 at the end became a 0), which meant the hex conversion was incorrect as well.
An easy solution is, since you already have the value as a string, would be to perform your own decimal->hex conversion.
One such algorithm can he found here:
https://stackoverflow.com/a/21668344/8237835
A small comparison of the results of Number#toString(16) and dec2hex(String):
function dec2hex(str){ // .toString(16) only works up to 2^53
var dec = str.toString().split(''), sum = [], hex = [], i, s
while(dec.length){
s = 1 * dec.shift()
for(i = 0; s || i < sum.length; i++){
s += (sum[i] || 0) * 10
sum[i] = s % 16
s = (s - sum[i]) / 16
}
}
while(sum.length){
hex.push(sum.pop().toString(16))
}
return hex.join('')
}
num = "76561198262006743"
console.log("dec2Hex: " + dec2hex(num))
console.log("toString: " + parseInt(num).toString(16))

JS concatenating object property values (numeric) instead of adding

In an intersect function, that checks if two objects intersect on the canvas, I need to add the obj.x and obj.width property to get the obj.right(side). Somehow the properties are concatenated instead of added. It probably has something to do with reference-type but I don't see how I can capture the values in primitive types.
function intersects(obj1, obj2) { // checks if 2 shapes intersect
var ob2x = obj2.x;
var ob2width = obj2.width;
if (obj1.x > +obj2.x + 70 || obj2.x > +obj1.x + 70) {
console.log('false : obj1.x=' + obj1.x + ' obj2.right=' + parseInt(ob2x) + parseInt(ob2width));
return false;
}
if (obj1.y > +obj2.y + +obj2.height || obj2.y > +obj1.y + +obj1.height) {
console.log('false');
return false;
}
console.log('false');
return true;
}
I have already tried to get the number value of the object property, as you can see. Didn't work
Also tried parseInt(), which didn't work.
I suppose I can put the values seperately as parameters in the fuctions but I was hoping to keep it as short as possible, because kids need to use it.
You need to add a grouping operator:
... + (parseInt(ob2x) + parseInt(ob2width)) + ...
to isolate that part of the expression so that + is seen as addition. Otherwise, the full expression keeps it as concatenation, even though you convert those to values to numbers (because if a string is anywhere in the expression being evaluated, + means concat).
E.g.
var x = 5;
var y = 6;
console.log('Sum: ' + x + y); // 56
console.log('Sum: ' + (x + y)); // 11

javascript split function not working

I have this following code.
var oldBeforeUnload = window.onbeforeunload;
window.onbeforeunload = function()
{
if(modifiedItems && modifiedItems != null)
{
var modifiedItemsArr = modifiedItems.split(",");
if(window.showModalDialog)
{
window.returnValue = modifiedItemsArr;
}
else
{
if (window.opener && window.opener.setFieldValue)
{
window.opener.setFieldValue(modifiedItemsArr);
}
}
}
return oldBeforeUnload();
};
when I split is run in IE it is throwing an
error : object doesnt support property or method split.
In ff the its exiting without any log.
on alert(modifiedItems) //the output is Ljava.lang.object;#c14d9
Can any one tell why is the split not working or is my modifiedItem wrong.
modifiedItems must be a string in order to use split.
alert(typeof modifiedItems);
var oldBeforeUnload = window.onbeforeunload;
window.onbeforeunload = function()
{
if(modifiedItems && modifiedItems != null)
{
alert(typeof modifiedItems);
var modifiedItemsArr = modifiedItems.split(",");
if(window.showModalDialog)
{
window.returnValue = modifiedItemsArr;
}
else
{
if (window.opener && window.opener.setFieldValue)
{
window.opener.setFieldValue(modifiedItemsArr);
}
}
}
return oldBeforeUnload();
};
variable "modifiedItems" should be a string for split function to work. In your case alert(modifiedItems) should alert the string value.I would suggest you to check "modifiedItems".
split() is a function in string object.
Split is a method that can be call on strings. It would seem as if you are trying to split an object not a string. Below is a correct and incorrect usage:
"a,s,d".split(",") // returns ['a','s','d']
{obj:true}.split(",") // will throw the error you are seeing becuase it is an object
To confirm this you can use the following:
console.log(typeof modifiedItems) // <- will output the vaiable type
modifiedItems should be an object, which you can not split, get the value for what you are trying to split out of modified items. On a different note, you are using the window namespace where it doesn't look like you need to be. Take a look at some of the links below to determine if you really should be using the window object.
Is setting properties on the Window object considered bad practice?
why attach to window [edited]
Use this cross browser method that will make everything work.
This script can be found out for downloading at:
http://blog.stevenlevithan.com/archives/cross-browser-split
It always has worked for me.
/*!
* Cross-Browser Split 1.1.1
* Copyright 2007-2012 Steven Levithan <stevenlevithan.com>
* Available under the MIT License
* ECMAScript compliant, uniform cross-browser split method
*/
/**
* Splits a string into an array of strings using a regex or string separator. Matches of the
* separator are not included in the result array. However, if `separator` is a regex that contains
* capturing groups, backreferences are spliced into the result each time `separator` is matched.
* Fixes browser bugs compared to the native `String.prototype.split` and can be used reliably
* cross-browser.
* #param {String} str String to split.
* #param {RegExp|String} separator Regex or string to use for separating the string.
* #param {Number} [limit] Maximum number of items to include in the result array.
* #returns {Array} Array of substrings.
* #example
*
* // Basic use
* split('a b c d', ' ');
* // -> ['a', 'b', 'c', 'd']
*
* // With limit
* split('a b c d', ' ', 2);
* // -> ['a', 'b']
*
* // Backreferences in result array
* split('..word1 word2..', /([a-z]+)(\d+)/i);
* // -> ['..', 'word', '1', ' ', 'word', '2', '..']
*/
var split;
// Avoid running twice; that would break the `nativeSplit` reference
split = split || function (undef) {
var nativeSplit = String.prototype.split,
compliantExecNpcg = /()??/.exec("")[1] === undef, // NPCG: nonparticipating capturing group
self;
self = function (str, separator, limit) {
// If `separator` is not a regex, use `nativeSplit`
if (Object.prototype.toString.call(separator) !== "[object RegExp]") {
return nativeSplit.call(str, separator, limit);
}
var output = [],
flags = (separator.ignoreCase ? "i" : "") +
(separator.multiline ? "m" : "") +
(separator.extended ? "x" : "") + // Proposed for ES6
(separator.sticky ? "y" : ""), // Firefox 3+
lastLastIndex = 0,
// Make `global` and avoid `lastIndex` issues by working with a copy
separator = new RegExp(separator.source, flags + "g"),
separator2, match, lastIndex, lastLength;
str += ""; // Type-convert
if (!compliantExecNpcg) {
// Doesn't need flags gy, but they don't hurt
separator2 = new RegExp("^" + separator.source + "$(?!\\s)", flags);
}
/* Values for `limit`, per the spec:
* If undefined: 4294967295 // Math.pow(2, 32) - 1
* If 0, Infinity, or NaN: 0
* If positive number: limit = Math.floor(limit); if (limit > 4294967295) limit -= 4294967296;
* If negative number: 4294967296 - Math.floor(Math.abs(limit))
* If other: Type-convert, then use the above rules
*/
limit = limit === undef ?
-1 >>> 0 : // Math.pow(2, 32) - 1
limit >>> 0; // ToUint32(limit)
while (match = separator.exec(str)) {
// `separator.lastIndex` is not reliable cross-browser
lastIndex = match.index + match[0].length;
if (lastIndex > lastLastIndex) {
output.push(str.slice(lastLastIndex, match.index));
// Fix browsers whose `exec` methods don't consistently return `undefined` for
// nonparticipating capturing groups
if (!compliantExecNpcg && match.length > 1) {
match[0].replace(separator2, function () {
for (var i = 1; i < arguments.length - 2; i++) {
if (arguments[i] === undef) {
match[i] = undef;
}
}
});
}
if (match.length > 1 && match.index < str.length) {
Array.prototype.push.apply(output, match.slice(1));
}
lastLength = match[0].length;
lastLastIndex = lastIndex;
if (output.length >= limit) {
break;
}
}
if (separator.lastIndex === match.index) {
separator.lastIndex++; // Avoid an infinite loop
}
}
if (lastLastIndex === str.length) {
if (lastLength || !separator.test("")) {
output.push("");
}
} else {
output.push(str.slice(lastLastIndex));
}
return output.length > limit ? output.slice(0, limit) : output;
};
// For convenience
String.prototype.split = function (separator, limit) {
return self(this, separator, limit);
};
return self;
}();

Why I got NaN in this javaScript code?

First I test that every variable got a number value:
09-11 18:15:00.420:
d_drop: -1.178791867393647
drop_at_zero: 0.0731037475605623
sightHeight: 4.5
d_distance: 40
zeroRange: 10
09-11 18:15:00.420:
d_drop: true
drop_at_zero: true
sightHeight: true
d_distance: true
zeroRange: true
function isNumber (o) {
return ! isNaN (o-0) && o != null;
}
var d_drop; // in calculation this gets value 1.1789
var d_path = -d_drop - sightHeight + (drop_at_zero + sightHeight) * d_distance / zeroRange;
console.log("Path: " + d_path + " cm");
and in the log:
09-11 18:15:00.430: D/CordovaLog(1533): Path: NaN cm
WHY? I have tried to figure that out couple of hours now and no success, maybe someone has an idea, I haven't!
Thanks!
Sami
-------ANSWER IS that parse every variable when using + operand-----------
var d_path = parseFloat(-d_drop) - parseFloat(sightHeight) + (parseFloat(drop_at_zero) + parseFloat(sightHeight)) * parseFloat(d_distance) / parseFloat(zeroRange);
The addition operator + will cast things as strings if either operand is a string. You need to parse ALL of your inputs (d_drop, sightHeight, etc) as numbers before working with them.
Here's a demo of how the + overload works. Notice how the subtraction operator - is not overloaded and will always cast the operands to numbers:
var numberA = 1;
var numberB = 2;
var stringA = '3';
var stringB = '4';
numberA + numberB // 3 (number)
numberA - numberB // -1 (number)
stringA + stringB // "34" (string)
stringA - stringB // -1 (number)
numberA + stringB // "14" (string)
numberA - stringB // -3 (number)
http://jsfiddle.net/jbabey/abwhd/
At least one of your numbers is a string. sightHeight is the most likely culprit, as it would concatenate with drop_at_zero to produce a "number" with two decimal points - such a "number" is not a number, hence NaN.
Solution: use parseFloat(varname) to convert to numbers.
If you're using -d_drop as a variable name, that is probably the culprit. Variables must start with a letter.
var d_drop = -1.178791867393647,
drop_at_zero = 0.0731037475605623,
sightHeight = 4.5,
d_distance = 40,
zeroRange = 10;
var d_path = d_drop - sightHeight + (drop_at_zero + sightHeight) * d_distance / zeroRange;
console.log("Path: " + d_path + " cm"); // outputs: Path: 12.613623122848603 cm

Javascript: How to retrieve the number of decimals of a *string* number?

I have a set of string numbers having decimals, for example: 23.456, 9.450, 123.01... I need to retrieve the number of decimals for each number, knowing that they have at least 1 decimal.
In other words, the retr_dec() method should return the following:
retr_dec("23.456") -> 3
retr_dec("9.450") -> 3
retr_dec("123.01") -> 2
Trailing zeros do count as a decimal in this case, unlike in this related question.
Is there an easy/delivered method to achieve this in Javascript or should I compute the decimal point position and compute the difference with the string length? Thanks
function decimalPlaces(num) {
var match = (''+num).match(/(?:\.(\d+))?(?:[eE]([+-]?\d+))?$/);
if (!match) { return 0; }
return Math.max(
0,
// Number of digits right of decimal point.
(match[1] ? match[1].length : 0)
// Adjust for scientific notation.
- (match[2] ? +match[2] : 0));
}
The extra complexity is to handle scientific notation so
decimalPlaces('.05')
2
decimalPlaces('.5')
1
decimalPlaces('1')
0
decimalPlaces('25e-100')
100
decimalPlaces('2.5e-99')
100
decimalPlaces('.5e1')
0
decimalPlaces('.25e1')
1
function retr_dec(num) {
return (num.split('.')[1] || []).length;
}
function retr_dec(numStr) {
var pieces = numStr.split(".");
return pieces[1].length;
}
Since there is not already a regex-based answer:
/\d*$/.exec(strNum)[0].length
Note that this "fails" for integers, but per the problem specification they will never occur.
You could get the length of the decimal part of your number this way:
var value = 192.123123;
stringValue = value.toString();
length = stringValue.split('.')[1].length;
It makes the number a string, splits the string in two (at the decimal point) and returns the length of the second element of the array returned by the split operation and stores it in the 'length' variable.
Try using String.prototype.match() with RegExp /\..*/ , return .length of matched string -1
function retr_decs(args) {
return /\./.test(args) && args.match(/\..*/)[0].length - 1 || "no decimal found"
}
console.log(
retr_decs("23.456") // 3
, retr_decs("9.450") // 3
, retr_decs("123.01") // 2
, retr_decs("123") // "no decimal found"
)
I had to deal with very small numbers so I created a version that can handle numbers like 1e-7.
Number.prototype.getPrecision = function() {
var v = this.valueOf();
if (Math.floor(v) === v) return 0;
var str = this.toString();
var ep = str.split("e-");
if (ep.length > 1) {
var np = Number(ep[0]);
return np.getPrecision() + Number(ep[1]);
}
var dp = str.split(".");
if (dp.length > 1) {
return dp[1].length;
}
return 0;
}
document.write("NaN => " + Number("NaN").getPrecision() + "<br>");
document.write("void => " + Number("").getPrecision() + "<br>");
document.write("12.1234 => " + Number("12.1234").getPrecision() + "<br>");
document.write("1212 => " + Number("1212").getPrecision() + "<br>");
document.write("0.0000001 => " + Number("0.0000001").getPrecision() + "<br>");
document.write("1.12e-23 => " + Number("1.12e-23").getPrecision() + "<br>");
document.write("1.12e8 => " + Number("1.12e8").getPrecision() + "<br>");
A slight modification of the currently accepted answer, this adds to the Number prototype, thereby allowing all number variables to execute this method:
if (!Number.prototype.getDecimals) {
Number.prototype.getDecimals = function() {
var num = this,
match = ('' + num).match(/(?:\.(\d+))?(?:[eE]([+-]?\d+))?$/);
if (!match)
return 0;
return Math.max(0, (match[1] ? match[1].length : 0) - (match[2] ? +match[2] : 0));
}
}
It can be used like so:
// Get a number's decimals.
var number = 1.235256;
console.debug(number + " has " + number.getDecimals() + " decimal places.");
// Get a number string's decimals.
var number = "634.2384023";
console.debug(number + " has " + parseFloat(number).getDecimals() + " decimal places.");
Utilizing our existing code, the second case could also be easily added to the String prototype like so:
if (!String.prototype.getDecimals) {
String.prototype.getDecimals = function() {
return parseFloat(this).getDecimals();
}
}
Use this like:
console.debug("45.2342".getDecimals());
A bit of a hybrid of two others on here but this worked for me. Outside cases in my code weren't handled by others here. However, I had removed the scientific decimal place counter. Which I would have loved at uni!
numberOfDecimalPlaces: function (number) {
var match = ('' + number).match(/(?:\.(\d+))?(?:[eE]([+-]?\d+))?$/);
if (!match || match[0] == 0) {
return 0;
}
return match[0].length;
}
Based on Liam Middleton's answer, here's what I did (without scientific notation):
numberOfDecimalPlaces = (number) => {
let match = (number + "").match(/(?:\.(\d+))?$/);
if (!match || !match[1]) {
return 0;
}
return match[1].length;
};
alert(numberOfDecimalPlaces(42.21));
function decimalPlaces(n) {
if (n === NaN || n === Infinity)
return 0;
n = ('' + n).split('.');
if (n.length == 1) {
if (Boolean(n[0].match(/e/g)))
return ~~(n[0].split('e-'))[1];
return 0;
}
n = n[1].split('e-');
return n[0].length + ~~n[1];
}

Categories

Resources