Amcharts - how to format valueField inside custom tooltip? - javascript

I've got a basic AmGraph:
graph = new AmCharts.AmGraph();
graph.lineThickness = 4;
graph.valueAxis = valueAxis;
graph.fillAlphas = 0;
graph.valueAxis = valueAxis;
graph.valueAxis.minimum = 0;
graph.title = "likes";
graph.labelText = " ";
graph.valueField = "likes_1";
The problem is that the numberFormatter doesn't format values if I'm using a custom balloonText function:
graph.numberFormatter = {precision: -1, decimalSeparator:",", thousandsSeparator:","};
So if I use this:
graph.balloonText = "<b>got: [[likes_1]] </b>";
The tooltip looks like this:
"got: 1000"
How can I format the value? if I try to use javascript for formatting it (Numeral.js):
graph.balloonText = "<script>numeral( [[likes_1]] ).format("0,0") </script>";
The wildcard isn't replaced with the actual value when building the page (but rather when hovering the chart?), so I just get:
Uncaught ReferenceError: likes_32 is not defined
What should I do?

(First I highly recommend to use the newer way of chart
initialization! Look
here
for that.)
Instead of balloonText you can use balloonFunction, which allows you to change the text with JavaScript. Inside there you can format the number according to your wishes.
I prepared a demo using the AmCharts.formatNumber formatter.
return AmCharts.formatNumber(graphDataItem.values.value, {
precision: -1,
decimalSeparator: '.',
thousandsSeparator: ','
}, -1);
You can still use Numeral.js in there though (it's syntax seems a little more straight forward to me).
return numeral(graphDataItem.values.value).format("0,0");

Related

Display floating point with starting values in DAT.GUI

I have a small menu made with dat.gui JavaScript library. I use different lines with some initial values which are displayed (these initial values are modified during the execution of code).
My issue is, for example, that instead of display a value "15", I would like to display "15.0000". I try to used toFixed(4) function but without success.
Here's the raw (without "toFixed(4)" function) code snippet :
var componentThetaInit = 15;
var componentPhiInit = 15;
var gui = new dat.GUI({
autoplace: false,
width: 350,
height: 9 * 32 - 1
});
var params = {
StartingVector : '',
ComponentVectorTheta : componentThetaInit,
ComponentVectorPhi : componentPhiInit
};
gui.add(params, 'StartingVector').name('Starting Vector :');
controllerComponentVectorTheta = gui.add(params, 'ComponentVectorTheta', minComponentTheta, maxComponentTheta, 0.0001).name('Component θ ');
controllerComponentVectorPhi = gui.add(params, 'ComponentVectorPhi', minComponentPhi, maxComponentPhi, 0.0001).name('Component φ ');
Now I tried :
var params = {
StartingVector : '',
ComponentVectorTheta : componentThetaInit.toFixed(4),
ComponentVectorPhi : componentPhiInit.toFixed(4)
};
but this doesn't work. Here's below a capture of what I get ("15" instead of "15.0000") before the execution :
Once the code is running, the 4 floating points are well displayed (because values are no more integers) : this is actually the initial values (before animation) that I would like to be displayed like "15.0000" instead of "15".
The result is the same by declaring :
var componentThetaInit = 15.0000;
var componentPhiInit = 15.0000;
I have also tried :
ComponentVectorTheta : parseFloat(componentThetaInit.toFixed(4)),
ComponentVectorPhi : parseFloat(componentPhiInit.toFixed(4))
If anyone could see what's wrong, this would be nice.
Thanks
First, some minor bugs. There were some missing variable declarations. I added:
var minComponentTheta = -10.0;
var maxComponentTheta = 100.0;
var minComponentPhi = -100.0;
var maxComponentPhi = 100.0;
2) The autoplace param (which should be autoPlace, capital P) has nothing to do with decimal places... it appears to be an option to automatically add the UI to the DOM.
None of this actually fixes the issue. It's a problem that starts with javascript. If you put this code in the console you'll see the same problem:
var a = 15.0000;
console.log(a);
// prints 15 and not 15.0000
When a number is an integer, it's an integer. To get around this, you can have your default value have a non integer value like 15.0001.
This probably isn't what you're looking for though. So, if you are up for modifying the code for dat.gui.js you can force it to set the value of the input to the string version of the number value. Find the code that looks like this and copy and paste the code below replacing it. I've simply added a toFixed at the end of the first line in the function. Be aware that when you get the value now, it will be a string and not a number, so to do math with it you'll want to parseFloat() on it before using it.
NumberControllerBox.prototype.updateDisplay = function updateDisplay() {
this.__input.value = this.__truncationSuspended ? this.getValue() : roundToDecimal(this.getValue(), this.__precision).toFixed(this.__precision);
return _NumberController.prototype.updateDisplay.call(this);
};
In the unminified JS version, ^ that's on line 2050.
I verified this works as you want
Just leave it like this:
ComponentVectorTheta : componentThetaInit.toFixed(4),
ComponentVectorPhi : componentPhiInit.toFixed(4)
Consider this:
a = 15; // a is an integer now
b = a.toFixed(4); // b is the string "15.0000"
c = parseFloat(b); // c is a number (internally, probably an integer)
d = c.toString(2); // d is the string "1111"
e = parseInt(d, 2);// e is an integer again
assert(a === e); // true

Wrong Math Algorithm with javascript?

im trying to make some Algorithm function with javascript and get some problems
function Algorithm() {
var endone;
var endtwo;
var endtheend;
var v1 = document.getElementsByName("v1")[0].value; //worth to 91
var v2 = document.getElementsByName("v2")[0].value; //worth to 61
var v3 = document.getElementsByName("v3")[0].value; //worth to 20
endone = Math.round(v1 * 0.30);
endtwo = Math.round(((v2 + v3) / 2) * 0.70);
endtheend = endone + endtwo;
document.getElementById("ending").innerHTML = "end : " + endtheend;
}
if im doing the same Algorithm with a calculator im getting 55.65 , but when im trying to use this function somehow im getting 2169.
someone might know what is the problem and show me how to solve her?
The problem is that v1, v2 and v3 are not numbers. They are strings. So each calculation you make is relies on implicit conversions and operations between strings.
For instance, in the following snippete we have an implicit conversion of the the string value "91" to a double floating number and then the usual mulitplication is done.
var v1 = "91";
console.log(v1*0.3);
On the other hand below:
var v2 = "61";
var v3 = "20";
console.log((v2 + v3) / 2)
We have a string concatenation "61"+"20" results in a new string "6120" and then "6120" is implicitly converted to a double floating number and the division with 2 is done.
What's the solution ?
You have to parse these values either by using parseInt or parseFloat, like below:
var v2 = "61";
var v3 = "20";
console.log((parseInt(v2,10) + parseInt(v3,10)) / 2)
When you get an HTMLInputElement's value property, what you get is a string.
And the + operator applied to two strings merely concatenates them, so if for instance v2 == "7" and v3 === "0", when you do (v2 + v3), you'll get "70".
The solution to your problem is to simply pass the values through parseInt:
var v1 = parseInt(document.getElementsByName("v1")[0].value, 10);
var v2 = parseInt(document.getElementsByName("v2")[0].value, 10);
var v3 = parseInt(document.getElementsByName("v3")[0].value, 10);
// The second argument to parseInt isn't needed if you only target newer browsers.
I'd suggest you read up on type coercion in JavaScript for more info.
The issue is all of your values (v1, v2, v3) are String type. You need to convert them into Number first. So the following code should work :
function Algorithm() {
var endone;
var endtwo;
var endtheend;
var v1 = Number(document.getElementsByName("v1")[0].value);
var v2 = Number(document.getElementsByName("v2")[0].value);
var v3 = Number(document.getElementsByName("v3")[0].value);
endone = Math.round(v1 * 0.30);
endtwo = Math.round(((v2 + v3) / 2) * 0.70);
endtheend = endone + endtwo;
document.getElementById("ending").innerHTML = "end : " + endtheend;
}
you can also use parseInt if your value contains any alphabetic characters.

dimple tickFormat ignores grouping comma

I have a dimple chart displaying some large numbers. I want the precise values to appear in the toolbox (not truncated to 14k) so I changed the tickFormat. However, dimple/d3 seems to ignore the grouping comma, which makes large numbers hard to process.
// this prints "12,345" as expected
var f = d3.format(",.0f");
console.log(f(12345.123));
var data = [{"date":"2016-01-18","completed":1234123.100},{"date":"2016-01-19","completed":1345123.0},{"date":"2016-01-20","completed":2123123.1}]
var svg = dimple.newSvg("#foo", "100%", "100%");
var myChart = new dimple.chart(svg, data);
var x = myChart.addTimeAxis("x", "date", "%Y-%m-%d", "%d/%m");
var y = myChart.addMeasureAxis("y", "completed");
// this does not work
// tooltips and y axis values appear without grouping comma
y.tickFormat = d3.format(",.0f");
myChart.setMargins("60px", "30px", "30px", "70px");
series = myChart.addSeries(null, dimple.plot.line);
myChart.draw();
According to the API documentation the property dimple.axis.tickFormat will accept the format specifier string (i.e. ",.0f"). as it is passed to d3.format(). You don't have to call d3.format() yourself; this is done internally in function _getFormat(). Thus your code becomes
y.tickFormat = ",.0f";

Replace array-mapped variables with the actual variable name/string?

I am trying to edit a Greasemonkey/jQuery script. I can't post the link here.
The code is obfuscated and compressed with minify.
It starts like this:
var _0x21e9 = ["\x67\x65\x74\x4D\x6F\x6E\x74\x68", "\x67\x65\x74\x55\x54\x43\x44\x61\x74\x65", ...
After "decoding" it, I got this:
var _0x21e9=["getMonth","getUTCDate","getFullYear", ...
It is a huge list (500+ ). Then, it has some variables like this:
month = date[_0x21e9[0]](), day = date[_0x21e9[1]](), ...
_0x21e9[0] is getMonth, _0x21e9[1] is getUTCDate, etc.
Is it possible to replace the square brackets with the actual variable name? How?
I have little knowledge in javascript/jQuery and can not "read" the code the way it is right now.
I just want to use some functions from this huge script and remove the others I do not need.
Update: I tried using jsbeautifier.org as suggested here and in the duplicated question but nothing changed, except the "indent".
It did not replace the array variables with the decoded names.
For example:
jsbeautifier still gives: month = date[_0x21e9[0]]().
But I need: month = date["getMonth"]().
None of the online deobfuscators seem to do this, How can I?
Is there a way for me to share the code with someone, at least part of it? I read I can not post pastebin, or similar here. I can not post it the full code here.
Here is another part of the code:
$(_0x21e9[8] + vid)[_0x21e9[18]]();
[8] is "." and [18] is "remove". Manually replacing it gives a strange result.
I haven't seen any online deobfuscator that does this yet, but the principle is simple.
Construct a text filter that parses the "key" array and then replaces each instance that that array is referenced, with the appropriate array value.
For example, suppose you have a file, evil.js that looks like this (AFTER you have run it though jsbeautifier.org with the Detect packers and obfuscators? and the Unescape printable chars... options set):
var _0xf17f = ["(", ")", 'div', "createElement", "id", "log", "console"];
var _0x41dcx3 = eval(_0xf17f[0] + '{id: 3}' + _0xf17f[1]);
var _0x41dcx4 = document[_0xf17f[3]](_0xf17f[2]);
var _0x41dcx5 = _0x41dcx3[_0xf17f[4]];
window[_0xf17f[6]][_0xf17f[5]](_0x41dcx5);
In that case, the "key" variable would be _0xf17f and the "key" array would be ["(", ")", ...].
The filter process would look like this:
Extract the key name using text processing on the js file. Result: _0xf17f
Extract the string src of the key array. Result:
keyArrayStr = '["(", ")", \'div\', "createElement", "id", "log", "console"]';
In javascript, we can then use .replace() to parse the rest of the JS src. Like so:
var keyArrayStr = '["(", ")", \'div\', "createElement", "id", "log", "console"]';
var restOfSrc = "var _0x41dcx3 = eval(_0xf17f[0] + '{id: 3}' + _0xf17f[1]);\n"
+ "var _0x41dcx4 = document[_0xf17f[3]](_0xf17f[2]);\n"
+ "var _0x41dcx5 = _0x41dcx3[_0xf17f[4]];\n"
+ "window[_0xf17f[6]][_0xf17f[5]](_0x41dcx5);\n"
;
var keyArray = eval (keyArrayStr);
//-- Note that `_0xf17f` is the key name we already determined.
var keyRegExp = /_0xf17f\s*\[\s*(\d+)\s*\]/g;
var deObsTxt = restOfSrc.replace (keyRegExp, function (matchStr, p1Str) {
return '"' + keyArray[ parseInt(p1Str, 10) ] + '"';
} );
console.log (deObsTxt);
if you run that code, you get:
var _0x41dcx3 = eval("(" + '{id: 3}' + ")");
var _0x41dcx4 = document["createElement"]("div");
var _0x41dcx5 = _0x41dcx3["id"];
window["console"]["log"](_0x41dcx5);
-- which is a bit easier to read/understand.
I've also created an online page that takes JS source and does all 3 remapping steps in a slightly more automated and robust manner. You can see it at:
jsbin.com/hazevo
(Note that that tool expects the source to start with the "key" variable declaration, like your code samples do)
#Brock Adams solution is brilliant, but there is a small bug: it doesn't take into account simple quoted vars.
Example:
var _0xbd34 = ["hello ", '"my" world'];
(function($) {
alert(_0xbd34[0] + _0xbd34[1])
});
If you try to decipher this example, it will result on this:
alert("hello " + ""my" world")
To resolve this, just edit the replacedSrc.replace into #Brock code:
replacedSrc = replacedSrc.replace (nameRegex, function (matchStr, p1Str) {
var quote = keyArry[parseInt (p1Str, 10)].indexOf('"')==-1? '"' : "'";
return quote + keyArry[ parseInt (p1Str, 10) ] + quote;
} );
Here you have a patched version.
for (var i = 0; i < _0x21e9.length; i++) {
var funcName = _0x21e9[i];
_0x21e9[funcName] = funcName;
}
this will add all the function names as keys to the array. allowing you to do
date[_0x21e9["getMonth"]]()

Google Apps Script - Dynamically Add Remove UiApp Form Elements

I am looking to create a Ui form section in my application that will Dynamically Add Remove UiApp Form Elements. I was trying to use the example from App Script Tutorials here
This example works great as far as performing the add remove elements, but when I use the submit button to capture the values, it submits as a JSON.stringify format. When I just want to capture the values only in a text or string format that will be added to a html email.
If there is way to convert JSON.stringify to text, string or get the values only in format, I will continue to use this example.
If not I was wonder if the following Javascript HTML code can be convert into GAS code and able to capture the values for each entry in a HTML email template to using in MailApp.
http://jsfiddle.net/g59K7/
Any suggestions, examples or adjustments to the codes would be greatly appreciated.
Thank you in advance
If you don't want the result to be in a JSON object, then you can adjust the _processSubmittedData(e) function. Right now he has it writing everything to an Object, which is fine. All you have to do is have a way to parse it:
function _processSubmittedData(e){
var result = {};
result.groupName = e.parameter.groupName;
var numMembers = parseInt(e.parameter.table_tag);
result.members = [];
//Member info array
for(var i=1; i<=numMembers; i++){
var member = {};
member.firstName = e.parameter['fName'+i];
member.lastName = e.parameter['lName'+i];
member.dateOfBirth = e.parameter['dob'+i];
member.note = e.parameter['note'+i];
result.members.push(member);
}
var htmlBody = 'Group Name: ' + result.groupName;
for(var a in result.members) {
var member = result.members[a];
var date = member.dateOfBirth;
var last = member.lastName;
var first = member.firstName;
var note = member.note;
htmlBody += first + ' ' + last + ' was born on ' + date + ' and has this note: ' + note;
}
MailApp.sendEmail('fakeEmail#fake.com',"Test Subject Line", "", {htmlBody: htmlBody});
}

Categories

Resources