<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<title>JS Bin</title>
</head>
<body>
</body>
</html>
;(function(global) {
// 'new' an object
const FormatNum = function(num, digits, unit) {
return new FormatNum.init(num, digits, unit);
}
// hidden within the scope of the IIFE and never directly accessible
const supportedUnit = ['normal', 'scientific'];
const unit = {
normalUnit: [
{ value: 1000000000, symbol: "B" },
{ value: 1000000, symbol: "M" },
{ value: 1000, symbol: "k" }
],
siUnit: [
{ value: 1E18, symbol: "E" },
{ value: 1E15, symbol: "P" },
{ value: 1E12, symbol: "T" },
{ value: 1E9, symbol: "G" },
{ value: 1E6, symbol: "M" },
{ value: 1E3, symbol: "k" }
],
}
// prototype holds methods (to save memory space)
FormatNum.prototype = {
validate: function() {
// check that is a valid language
// references the externally inaccessible 'supportedUnit' within the closure
if (supportedUnit.indexOf(this.unit) === -1) {
throw "Invalid unit";
}
},
calculate: function(unitType) {
const unitMap = unit[unitType];
const rx = /\.0+$|(\.[0-9]*[1-9])0+$/;
for (let i = 0; i < unitMap.length; i++) {
if (this.num >= unitMap[i].value) {
return (this.num / unitMap[i].value).toFixed(this.digits || 1).replace(rx, "$1") + unitMap[i].symbol;
}
}
},
formatScientific: function() {
return this.calculate('siUnit');
},
formatNormal: function() {
return this.calculate('normalUnit');
},
// chainable methods return their own containing object
format: function(unit) {
let formattedNum;
// if undefined or null it will be coerced to 'false'
if (unit === 'scientific') {
formattedNum = this.formatScientific();
}
else {
formattedNum = this.formatNormal();
}
this.formattedNum = formattedNum;
// 'this' refers to the calling object at execution time
// makes the method chainable
return this;
},
log: function() {
if (console) {
console.log('formattedNum is: ' + this.formattedNum);
}
// make chainable
return this;
},
};
// the actual object is created here, allowing us to 'new' an object without calling 'new'
FormatNum.init = function(num, digits, unit) {
const self = this;
self.num = num || '';
self.digits = digits || '';
self.unit = unit || 'normal';
self.validate();
};
// trick borrowed from jQuery so we don't have to use the 'new' keyword
FormatNum.init.prototype = FormatNum.prototype;
global.FormatNum = global.F$ = FormatNum;
}(window));
Output
You can jump to the latest bin by adding /latest
to your URL
Keyboard Shortcuts
Shortcut | Action |
---|---|
ctrl + [num] | Toggle nth panel |
ctrl + 0 | Close focused panel |
ctrl + enter | Re-render output. If console visible: run JS in console |
Ctrl + l | Clear the console |
ctrl + / | Toggle comment on selected lines |
ctrl + ] | Indents selected lines |
ctrl + [ | Unindents selected lines |
tab | Code complete & Emmet expand |
ctrl + shift + L | Beautify code in active panel |
ctrl + s | Save & lock current Bin from further changes |
ctrl + shift + s | Open the share options |
ctrl + y | Archive Bin |
Complete list of JS Bin shortcuts |
JS Bin URLs
URL | Action |
---|---|
/ | Show the full rendered output. This content will update in real time as it's updated from the /edit url. |
/edit | Edit the current bin |
/watch | Follow a Code Casting session |
/embed | Create an embeddable version of the bin |
/latest | Load the very latest bin (/latest goes in place of the revision) |
/[username]/last | View the last edited bin for this user |
/[username]/last/edit | Edit the last edited bin for this user |
/[username]/last/watch | Follow the Code Casting session for the latest bin for this user |
/quiet | Remove analytics and edit button from rendered output |
.js | Load only the JavaScript for a bin |
.css | Load only the CSS for a bin |
Except for username prefixed urls, the url may start with http://jsbin.com/abc and the url fragments can be added to the url to view it differently. |