Mystery code: +i+ and +x+ - javascript

In the following code:
for (i=0; i<itemsinlist.length; i++) {
var rating = document.createElement('div');
itemsinlist[i].appendChild(rating);
rating.className = "rating";
rating.id = "thumbnails" +i;
for (x=0; x<4; x++) {
star = document.createElement('span');
star.innerHTML = "★";
star.className = "star";
star.setAttribute("onclick", "ratingsSet("+i+","+x+");");
rating.appendChild(star);
} //createratingsstars
I'm struggling to make sense of the second parameter to star.setAttribute(), in the line:
star.setAttribute("onclick", "ratingsSet("+i+","+x+");");
Specifically, I'm being thrown off by the +i+ and +x+.
At first I thought these were some kind of variation on the increment operator, but later decided it must be concatenating something, but I can't figure out what/how. The HTML that gets generated by the loop is:
<span class="star" onclick="ratingsSet(0,0);">*</span>
<span class="star" onclick="ratingsSet(0,1);">*</span>
<span class="star" onclick="ratingsSet(0,2);">*</span>
<span class="star" onclick="ratingsSet(0,3);">*</span>
But my reverse-engineering chops are failing me (if I had any to begin with).
Help?

It's string concatenation. i is the outer loop counter, and x is the inner loop counter. It appears to be iterating a collection and creating 4 spans per item.

It's putting together this string:
"ratingsSet(0,1);"
The value 0 is in the variable i, and the value 1 is in the variable x. If we add some spaces, it might be more clear:
"ratingsSet(" + i + "," + x + ");"

As far as I can tell it increments i and x and sets attribute on click for element that is:
"ratingsSet("+i+","+x+");"
Then after click ratingsSet("+i+","+x+"); with params is executed.
Weird way of doing it.

You can have more readable code:
star.onclick = function() {
ratingsSet(i, x);
};
Setting event handler as attribute breaks in older browsers plus not very elegant.

JavaScript allows you to concatenate strings and integers (and, AFAIK, the string representation of any object) with the plus operator. The resulting HTML (with its embedded JavaScript!) is just that: instantiations of calls to ratingsSet().

"+" is a infix operator that concatenate two strings.
Example : "mor"+"ning" will give the string "morning".
So it simply print the value of i or x to the HTML.

I have the same question, now i know i have made a funny mistake. You must read this statement in a wrong way like me. This second argument need a string, so "ratingsSet("+i+","+x+");" means
"ratingsSet("+i+","+x+"):"
so this argument will become a string. There are no +x+
:)

Related

How to write a function that adds a function inside a function in a string?

I'm going to try my best to explain this string manipulation.
I would like to write a JavaScript function that takes a string (preferably from a message textbox but it will be initially stored in a variable for this example) and looks for every instance of the power function "Pow()". Then, takes the contents of the "base" portion of the power function "Pow(base,exponent)" and replace it with the absolute function "Abs()" with the contents inside that so the result is "Pow(Abs(base),exponent)". The base can be anything; a word, an equation, or another function. result out to another message textbox.
for example
input:
return(1.0-step(snoise(vec2(5.0*pow(iGlobalTime,2.0)+pow(uv.x*7.0,1.2),pow((mod(iGlobalTime,100.0)+100.0)*uv.y*0.3+3.0,staticHeight))),staticAmount))*staticStrength;
output:
return(1.0-step(snoise(vec2(5.0*pow(abs(iGlobalTime),2.0)+pow(abs(uv.x*7.0),1.2),pow(abs((mod(iGlobalTime,100.0)+100.0)*uv.y*0.3+3.0),staticHeight))),staticAmount))*staticStrength;
I'm well aware of the .match and string.replace() functions but this is a little more complex.
Can anyone lead me in the right direction?
<textarea id = "output" rows="25" cols="55" ></textarea>
<script>
inputStr = "return(1.0-step(snoise(vec2(5.0*pow
(iGlobalTime,2.0)+pow(uv.x*7.0,1.2),pow
((mod(iGlobalTime,100.0)+100.0)*uv.y*0.3+3.0,
staticHeight))),staticAmount))*staticStrength;"
function baseReplacer(input)
{
}
var outputStr = baseReplacer(inputStr);
document.getElementById("output").value = outputStr;
</script>
I will try to describe the pseudo algorithm:
For every match of the substring pow(:
From the next position, you either will find nested brackets in first argument, or a simple argument, and then a comma.
If you find brackets, iterate through each position adding +1 to a counter every open bracket, and -1 for every close bracket. When the counter is set to zero, next comma is sure to end the first parameter string.
Got the idea ?
Happy 2020 ;)

What is the best way to access an element through a data-attribute whose value is an object (JSON)?

Say I have the following element:
<div class='selector' data-object='{"primary_key":123, "foreign_key":456}'></div>
If I run the following, I can see the object in the console.
console.log($('.selector').data('object'));
I can even access data like any other object.
console.log($('selector').data('object').primary_key); //returns 123
Is there a way to select this element based on data in this attribute? The following does not work.
$('.selector[data-object.foreign_key=456]');
I can loop over all instances of the selector
var foreign_key = 456;
$('.selector').each(function () {
if ($(this).data('object').foreign_key == foreign_key) {
// do something
}
});
but this seems inefficient. Is there a better way to do this? Is this loop actually slower than using a selector?
You can try the contains selector:
var key_var = 456;
$(".selector[data-object*='foreign_key:" + key_var + "']");
I think that you may gain a little speed here over the loop in your example because in your example jQuery is JSON parsing the value of the attribute. In this case it's most likely using the JS native string.indexOf(). The potential downside here would be that formatting will be very important. If you end up with an extra space character between the colon and the key value, the *= will break.
Another potential downside is that the above will also match the following:
<div class='selector' data-object="{primary_key:123, foreign_key:4562}"></div>
The key is clearly different but will still match the pattern. You can include the closing bracket } in the matching string:
$(".selector[data-object*='foreign_key:" + key_var + "}']");
But then again, formatting becomes a key issue. A hybrid approach could be taken:
var results = $(".selector[data-object*='" + foreign_key + "']").filter(function () {
return ($(this).data('object').foreign_key == foreign_key)
});
This will narrow the result to only elements that have the number sequence then make sure it is the exact value with the filter.
With a "contains" attribute selector.
$('selector[data-object*="foreign_key:456"]')

Javascript and using variables instead of strings in bracket notation

I have a PHP script that takes a text list with a variable number of questions and generates HTML form code that looks like this.
What did you think of X?<br />
<input type="hidden" name="$survey[0][0]" value="What did you think of X?">
<input type="radio" name="$survey[0][1]" value="1">Didn't like it.
<input type="radio" name="$survey[0][1]" value="2">I was indifferent.
<input type="radio" name="$survey[0][1]" value="3">Liked it.
$survey[n][0] is the question, $survey[n][1] is the answer, and n is the variable number of questions.
To validate using Javascript, I have a loop that loops through the questions, and a loop inside it that makes sure each question has an answer. My problem is referencing the elements with [] in their names. Here's what I think is the relevant part of my code.
var formElements = document.forms["form"].elements;
var groupCount = document.getElementsByTagName("li").length;
var groupNdx = 0;
var groupName = "";
var btnCount = 0;
while (groupNdx < groupCount) {
groupName = "'$survey[" + groupNdx + "][1]'";
btnCount = formElements[groupName].length;
That last line doesn't work because formElements[groupName] is "undefined."
formElements['$survey[3][1]'] works just fine, but that hardcodes the element's name, and I'd need to repeat the code for each question, and worse, it's a variable number of questions.
As I was typing, the Similar Questions sidebar suggested I read Why aren't variable names converted to strings when using bracket notation in javascript?, so now I that's just how it is in Javascript.
But then what workaround would you suggest? I could just forget about validating with Javascript since I also validate the form with PHP, but I understand it's good practice to validate forms at both the client and server sides. Thanks for your help!
You have an extra set of single quotes that you shouldn't here:
groupName = "'$survey[" + groupNdx + "][1]'";
That adds single quotes into the key itself. Change that to:
groupName = "$survey[" + groupNdx + "][1]";
Notice that x["'key'"] is a different from x['key'] in Javascript. The first has a key of 'key' (including the quotes) while the second has just the string: key

Replace Word Within Word - Javascript

I need to get a id from a html element and replace a part of the word. For example:
HTML
<input type="checkbox" id="facebookCheckbox"></div>
JavaScript
var x = document.getElementById("facebookCheckbox");
var name = x.id;
name.replace("Checkbox","");
This obviously does not work because the replacing word has to be standalone for it to be replaced. Is there a different way of doing this?
I'm looking for purely javascript no jQuery
Thank you!
name.replace("Checkbox","");
This obviously does not work because the replacing word has to be standalone for it to be replaced.
No, it does work and there's no need to be "standalone" - any part of the string can be matched. Only you did nothing with the result of the operation:
console.log(name.replace("Checkbox",""));
// or
name = name.replace("Checkbox","");
// or assign back to x.id maybe?
You are creating a copy of string when replacing, so you must assign the result of .replace() back to x.id.
var x = document.getElementById("facebookCheckbox");
x.id = x.id.replace("Checkbox","");
this is not going to work in this way. However you can have a marker kind of character by which you can break the name into array and implement the logic. For example:
var x = document.getElementById("facebook_Checkbox");
//Note I have added underscore in the Id
var name = x.id;
var arr=name.split("_");
//Now you have Checkbox and Facebook as string objects (part of array) and you can use them
name=arr[0]
I hope it will solve the purpose.

each() function returning Null or Objects

Hi I am newbie in programming and I am trying to learn and make it work with each(). Bear with me. I try my best to learn from here and you.
I am trying to go through the item per product in a catalog for the specific prices: either original and sale from the page.
then calculate the % for discount
print discount %
check to compare the percent to color the background: brown, yellow and red.
Now, I test each line to see if it works or not.
salecost = $(this).find('#sale').html(); returns a few nulls before displays amount with dollar signs. Weird couldn't figure that one out. Replace() isn't working right - couldn't get it working. It is supposed to remove dollar sign.
Also, I am not sure how it goes with compare -- do i write statement correctly?
Thank you in advance for the help
var salecost;
var originalcost;
var percentDiscount;
var percent;
function calculate(sale, original)
{
percentDiscount = eval((sale/original)*100);
document.getElementById("percentoff").innerHTML=parseInt(percentDiscount) + '%';
}
$(document).ready(function(index){
$('.item').each(function(){
salecost = $(this).find('#sale').html();
salecost = salecost.replace(/[^\d\.]/g,"");
alert (salecost);
originalcost = $('#sale').html();
originalcost = originalcost.replace(/[^\d\.]/g,"");
alert (originalcost);
percent = calculate(salecost,originalcost);
alert(percent);
if(percent<30)
{
$("div#percentoff").css({"background-color":"brown", "padding":"5px 0"});
}
if(percent<50){
$("div#percentoff").css({"background-color":"yellow", "padding":"5px 0"});
}
if(percent<70){
$("div#percentoff").css({"background-color":"red", "padding":"5px 0"});
}
});
});
This is not required
$(this).find('#sale').html();
You can replace this using
$("#sale").html();
since id will be unique in a document. If you have more than one element with the same id then your HTML is invalid.
Edit
Remove the id from the span tag.
<span class="price">S$319</span>
This will find all the spans[here only 1] with class name price inside the parent div. No need to use .html() here, you can use .text()
$(this).find('span.price').text();
You should move your var statements to within the each function so they're not global.
You don't need to you the eval, (sale/original)*100 will work by it self.
It's better to use consistent style, your calculate function could be written using jquery.
$("#percentoff").html(percentDiscount) + '%');
casting is unnecessary for most cases in javascript, concatenating a number with a string will produce a string.
your calculate function should return percentDiscount;
Instead of using .css() it would be better to use .addClass that way it's easy to undo with .removeClass, the style is all the the style sheet and you can use jquery to select the elements with the class.

Categories

Resources