I'm having a weird issue in JS comparing strings. One string is from a user input.
y = data;
document.getElementById("typeThisWord").innerHTML = y;
x = document.getElementById("inputField");
document.getElementById("youTyped").innerHTML = x.value;
first = document.getElementById("youTyped");
second = document.getElementById("typeThisWord");
if(first==second) correct=true;
When the words are the same, it still comes out false. I added in the 'first' and 'second' variables just to see if it would make a difference. Previously I've tried just comparing 'x' to 'y'. I've also tried x.value==y, x==y.value, and x.value==y.value. THe same with 'first' and 'second.' Surprisingly first.value==second.value came out to be true all the time, even when it shouldn't be.
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<script>
var x, y;
var first, second;
var availV = window.innerHeight - 100;
var availH = window.innerWidth - 100;
var randV, randH;
var correct = new Boolean(); correct=true;
var imageX;
function displayWord() {
if(correct) {
correct=false;
$.ajax({
url: "http://localhost:25578/TypeGood/VisitsSession",
success: function(data) { y = data; },
async: false
});
document.getElementById("typeThisWord").innerHTML = y;
imageX = document.createElement("img");
imageX.src = "https://encrypted-tbn1.gstatic.com/images?q=tbn:ANd9GcRPRV4XdE7C9sa0pM-FeXcOSQydg7Sh0INg-ZD6FKZ4wjY8WPHa5Q";
imageX.height = 100;
imageX.width = 100;
imageX.style.position = "absolute";
randV = Math.round( Math.random() * availV );
randH = Math.round( Math.random() * availH );
imageX.style.top = randV + "px";
imageX.style.left = randH + "px";
imageX.style.zIndex = "-20";
document.body.appendChild(imageX);
}
x = document.getElementById("inputField");
document.getElementById("youTyped").innerHTML = x.value;
first = document.getElementById("youTyped").innerHTML;
second = document.getElementById("typeThisWord").innerHTML;
if(first==second) {correct=true;}
x.value = "";
}
</script>
getElementById returns a reference to a DOM element, not a string, so you're not comparing strings, you're comparing DOM elements. Since they're different elements, they aren't ==.
At a minimum, your last three lines should be something like:
first = document.getElementById("youTyped").innerHTML;
second = document.getElementById("typeThisWord").innerHTML;
if(first==second) correct=true;
(E.g., using the innerHTML of the elements, which is a string.) Although I think I'd probably keep the values around in variables rather than going back to the DOM for them.
For Example:
y = data; //data is string value "First"
Change this value to new string "first" >> here f is small
y2 = "first"
Now, When both are of same type, its case sensitive.
if(y==y2)
so values are..
First == first
that will be false.
So make sure of data you are passing in inner html. and make sure you are not adding some white space to it..
I hope this may solve problem. :)
comment back if not solved after modifying the code :)
use this instead of (first==second):
if(first===second)
and retrieve value from html like this:
first = document.getElementById("youTyped").innerHTML;
Related
When I add two variables that I initialize as numbers, JS considers them as a string and concatenates them. In a calculation as follows,
var p1 = new window.TRIGEO.Point(150, 150);
var p2 = new window.TRIGEO.Point(500, 350);
var p3 = new window.TRIGEO.Point(50, 500);
var medicentre = new Point((p1.x+p2.x+p3.x)/3,(p1.y+p2.y+p3.y)/3);
(where Point has x and y as members),medicentre is huge =>( 5016683.33 , 50116833.33 ). I do not want this when the answer is actually =>( 233.33 , 333.33 ).
Is there any way to override this behaviour without making the formula too long, cause I have another one, which is at least three lines long. Is this possible without using parseInt()?
EDIT:
Point object is the following and that's it!
function Point(x, y) {
this.x = x;
this.y = y;
}
TRIGEO is the name of the library I'm writing to visualize all the important points and line segments of a triangle. Sorry for the confusion, I probably should've edited.
whilst Parsint as already answered is technically correct, if you want a shorter formula you can trick the casting by making your values positive (as long as you know they aren't going to have non-numberic values
var num1 = '1111.11';
var num2 = 2222.22;
var n1plus2 = (+num1)+num2
// n1p2 : 3333.33
or both strings:
var num1 = '1111.11';
var num2 = '2222.22';
var n1p2 = (+num1)+(+num2);
// n1p2 : 3333.33
JavaScript doesn't consider them as string. You probably execute an operation in the Point class and convert them.
function A(x, y) {
this.x = x;
this.y = y;
}
var a = new A(1, 1),
b = new A(2, 2),
c = new A(a.x + b.x, a.y + b.y);
alert(c.x + " - " + c.y)
This will output 3 - 3 as expected.
My issue concern 3 variables :
var modifyForce = 2;
var forceBase = 15;
var Force = (forceBase + modifyForce);
It display 17 Force
The first function which is working is :
{
Force++;
document.getElementById("Force").innerHTML = Force;
}
It adds +1 to Force each time I call it
But the second function :
{
forceBase++;
document.getElementById("Force").innerHTML = Force;
}
Does not add +1 to Force. Since it should add +1 to forceBase and Force = forceBase + modifyForce then it should add 1 to Force... I think.
My goal is to have a "forceBase" statistic + a "modifyForce" in order to get a total of "Force"
I am probably missing something simple but I can't find what. :/
Thank you :)
The problem is you're not updating Force to be equal to the new forceBase + modifyForce. Beyond declaration, Force doesn't keep any connection to forceBase or modifyForce, and you have to manually assign the new value to it. You should change your code as such:
{
forceBase++;
Force = forceBase + modifyForce;
document.getElementById("Force").innerHTML = Force;
}
Keep in mind that if Force is changed in another function (such as the first one you posted), this will reset those changes.
No one seems to have suggested this yet...
If you want Force to always be forceBase + modifyForce then make it a function.
function Force(){
return forceBase + modifyForce
}
Which now makes this work (note Force is now called with ():
{
forceBase++;
document.getElementById("Force").innerHTML = Force();
}
var modifyForce = 2;
var forceBase = 15;
var Force = (forceBase + modifyForce);
Force is one time calculated with forceBase + modifyForce
After the declaration you just have the number saved in Force
If you would like to use Force as a function to add modifyForce to forceBase use something like
var Force = function () {
return forceBase + modifyForce;
}
but you can't increment it like Force++ :P
The code-block where you edit forceBase does not re-calculate the updated value of Force.
To make this simple I recommend you move the re-calcultation and output into a distinct function like this:
var modifyForce = 2;
var forceBase = 15;
function updateForce() {
var Force = (forceBase + modifyForce);
document.getElementById("Force").innerHTML = Force;
}
// Output the current value of Force
updateForce(); // output is 17
forceBase++;
updateForce(); // output is 18
modifyForce++;
updateForce(); // output is 19
The best thing might be to create a class:
var objForce = {
modifyForce: 2,
forceBase: 15,
Force: 17,
reCalculate: function() {
this.Force = this.modifyForce + this.forceBase;
}
};
objForce.forceBase++;
objForce.reCalculate();
document.getElementById("Force").innerHTML = objForce.Force;
This is the rounding function we are using (which is taken from stackoverflow answers on how to round). It rounds half up to 2dp (by default)
e.g. 2.185 should go to 2.19
function myRound(num, places) {
if (places== undefined) {
// default to 2dp
return Math.round(num* 100) / 100;
}
var mult = Math.pow(10,places);
return Math.round(num* mult) / mult;
}
It has worked well but now we have found some errors in it (in both chrome and running as jscript classic asp on IIS 7.5).
E.g.:
alert(myRound(2.185)); // = 2.19
alert (myRound(122.185)); // = 122.19
alert (myRound(511.185)); // = 511.19
alert (myRound(522.185)); // = 522.18 FAIL!!!!
alert (myRound(625.185)); // = 625.18 FAIL!!!!
Does anyone know:
Why this happens.
How we can round half up to 2 dp without random rounding errors like this.
update: OK, the crux of the problem is that in js, 625.185 * 100 = 62518.499999
How can we get over this?
Your problem is not easily resolved. It occurs because IEEE doubles use a binary representation that cannot exactly represent all decimals. The closest internal representation to 625.185 is 625.18499999999994543031789362430572509765625, which is ever so slightly less than 625.185, and for which the correct rounding is downwards.
Depending on your circumstances, you might get away with the following:
Math.round(Math.round(625.185 * 1000) / 10) / 100 // evaluates to 625.19
This isn't strictly correct, however, since, e.g., it will round, 625.1847 upwards to 625.19. Only use it if you know that the input will never have more than three decimal places.
A simpler option is to add a small epsilon before rounding:
Math.round(625.185 * 100 + 1e-6) / 100
This is still a compromise, since you might conceivably have a number that is very slightly less than 625.185, but it's probably more robust than the first solution. Watch out for negative numbers, though.
Try using toFixed function on value.
example is below:
var value = parseFloat(2.185);
var fixed = value.toFixed(2);
alert(fixed);
I tried and it worked well.
EDIT: You can always transform string to number using parseFloat(stringVar).
EDIT2:
function myRound(num, places) {
return parseFloat(num.toFixed(places));
}
EDIT 3:
Updated answer, tested and working:
function myRound(num, places) {
if (places== undefined) {
places = 2;
}
var mult = Math.pow(10,places + 1);
var mult2 = Math.pow(10,places);
return Math.round(num* mult / 10) / mult2;
}
EDIT 4:
Tested on most examples noted in comments:
function myRound(num, places) {
if (places== undefined) {
places = 2;
}
var mult = Math.pow(10,places);
var val = num* mult;
var intVal = parseInt(val);
var floatVal = parseFloat(val);
if (intVal < floatVal) {
val += 0.1;
}
return Math.round(val) / mult;
}
EDIT 5:
Only solution that I managed to find is to use strings to get round on exact decimal.
Solution is pasted below, with String prototype extension method, replaceAt.
Please check and let me know if anyone finds some example that is not working.
function myRound2(num, places) {
var retVal = null;
if (places == undefined) {
places = 2;
}
var splits = num.split('.');
if (splits && splits.length <= 2) {
var wholePart = splits[0];
var decimalPart = null;
if (splits.length > 1) {
decimalPart = splits[1];
}
if (decimalPart && decimalPart.length > places) {
var roundingDigit = parseInt(decimalPart[places]);
var previousDigit = parseInt(decimalPart[places - 1]);
var increment = (roundingDigit < 5) ? 0 : 1;
previousDigit = previousDigit + increment;
decimalPart = decimalPart.replaceAt(places - 1, previousDigit + '').substr(0, places);
}
retVal = parseFloat(wholePart + '.' + decimalPart);
}
return retVal;
}
String.prototype.replaceAt = function (index, character) {
return this.substr(0, index) + character + this.substr(index + character.length);
}
OK, found a "complete" solution to the issue.
Firstly, donwnloaded Big.js from here: https://github.com/MikeMcl/big.js/
Then modified the source so it would work with jscript/asp:
/* big.js v2.1.0 https://github.com/MikeMcl/big.js/LICENCE */
var Big = (function ( global ) {
'use strict';
:
// EXPORT
return Big;
})( this );
Then did my calculation using Big types and used the Big toFixed(dp), then converted back into a number thusly:
var bigMult = new Big (multiplier);
var bigLineStake = new Big(lineStake);
var bigWin = bigLineStake.times(bigMult);
var strWin = bigWin.toFixed(2); // this does the rounding correctly.
var win = parseFloat(strWin); // back to a number!
This basically uses Bigs own rounding in its toFixed, which seems to work correctly in all cases.
Shame Big doesnt have a method to convert back to a number without having to go through a string.
I am still new to Javascript and JQuery. I have written a small function I run from document-ready. Its purpose is to set the height of a div as a multiple of line-heights:
function setLoginLinksHeight(numOfLines) {
var ll = hash(LOGIN_LINKS);
$(ll).css('line-height','130%');
var lh = $(ll).css('line-height');
var nh = lh * numOfLines; // Issue here
$(ll).height(nh);
}
From FireBug, the line-height I retrieve is 15.5833px. When I multiply it by 2 (for example), nh is set to NaN. I saw in this question that the retrieved value can have any format (%, px, etc...). This is scary!
How can I convert the returned value into a number of pixels without units into order to be able to create multiples of it? Is there a library/function available for this in Javascript or JQuery? What is the recommended practice in this case? Thanks.
EDIT
I have developed a small unit splitter following mblase75's solution:
function splitUnit(e) {
var eUnit = '';
var eValue;
if( e && ( length = e.search( /px/ ) ) ) {
eUnit = 'px';
eValue = e.substr( 0, length );
} else if ( e && ( length = e.search( /em/ ) ) ) {
eUnit = 'em';
eValue = e.substr( 0, length );
} else {
eValue = e;
}
return new Array( eValue, eUnit );
}
Change to:
var lh = parseFloat($(ll).css('line-height'));
Of course, this doesn't guarantee that you'll be getting a number of pixels, just that you'll be getting a number. To extract the units separately, add:
var lhunits = $(ll).css('line-height').match(/\D+$/)[0];
// gets first element of array
...and then combine the calculation with the old units:
var nh = (lh*numOfLines) + lhunits;
var test = "15.83333px";
alert(parseFloat(test));
Just tried this in jsFiddle. Worked as expected and returned the value without pixels
Here's my code:
var frameWidth = 400;
var imageWidth = $('#inner-image').css('width');
var numberOfFrames = imageWidth/frameWidth;
How do I make "numberOfFrames" display as a quotient? I.E. process "frameWidth" and "imageWidth" as numbers, rather than objects?
Let me know if I need to explain myself more clearly. Thanks!
.css('width') is likely returning the value with px. You can use parseInt() to get only the number.
var frameWidth = 400;
var imageWidth = parseInt( $('#inner-image').css('width'), 10);
var numberOfFrames = imageWidth/frameWidth;
The second argument 10 specifies the base that parseInt() should use.
You can also use the width()(docs) method to get the result without the px.
var frameWidth = 400;
var imageWidth = +$('#inner-image').width();
var numberOfFrames = imageWidth/frameWidth;
Here I used the unary + operator to make it a Number instead of a String.