Javascript Dynamic variable names not working - javascript

I have a table in a form with a list of products where there is an input for each (let's call it 'pc'). Each input is named as 'pc' and product id with an id as the same. IE: 'pc100', 'pc101', etc. Each input has an onkeyup event to call a function to populate a price where I pass the product id (onkeyup='myfunction(100) The function receives the id but I cannot configure the javascript to that id. I will have the rest of the code as long as I can get the dynamic variable name. The internet is full of all kinds of things like eval() and window[] and I have tried every possible combination I can think of/find. I know it's possible to get this to work. So...how can I get this alert to work?
Most the results I will give me 'pc100' when I need 'Heres my test'
function myfunction(idpro) {
var pc331 = 'Heres my test';
alert( "pc" + idpro );
}

Don't use dynamic variable names. Do use look-ups in data structures:
function f(id) {
var pc = {
331: "Here's my test"
}
console.log(pc[id]);
}
Dynamic variables are a huge problem, especially from a security perspective. If you were naive and used eval someone could construct an id value that executes arbitrary JavaScript and then you have an XSS problem.

Related

How to pass an array from javascript to php

So i've been asked to remake some registration forms. The way its supposed to work is, that an interpreter chooses X amount of languages in the first select box. Then based on the selections of languages, the user must specify from which languages they can translate from/to.
I want to store this data in a key/value array, with the key being "LanguageFrom" and Value being another array, of "LanguagesTo". This is how i have solved this:
function btnTest() {
var fromArray = $('.freelancerLanguagesFrom').map(function() {
return $(this).val();
}).get();
var toArray = $('.freelancerLanguagesTo').map(function() {
return $(this).val();
}).get();
var tempArray = {};
tempArray[fromArray] = toArray;
}
This method is being called with an "onclick" function in the html part. The user should specify which languages he can translate to for each of the chosen languages in the first box,
I am aware that this probably isn't the ideal approach, but im still an inexperienced developer, and i'd love to hear your take on another approach.
Now comes my problem:
1) How do i make it so the array wont overwrite the existing array with each button click, and instead just add to the array?
2) How do i process this array on the server side (php), so that i can store the values in my database?
3) Is it possible to skip the flow where the user has to press the save(gem) button after each language he has chosen?
edit: Question 1 and 3 are now solved, my only problem is accessing the array i made in js, on the php side
1) tempArray exists only in the scope of the btnTest() function. Declare it outside (in the global scope), initialize it as {} and don't reset it every time you click the button. The way you get the fromArray variable may require some tweaking depending on whether the "from" list can accept a multiple selection or not.
2) Ajax may help. Create a php endpoint to receive the request and call it using ajax. You can work on the array using JSON. Send your data using JSON.stringify(tempArray) and read it using json_decode() in your php script, or simply set the request headers as "application/json" to have it done automatically for you.
3) I personally wouldn't automate this process. Let's say I have 4 languages, Italian, English, French and Chinese.
I have selected a desirable state of languages I can handle:
Italian -> English, French
But I also know how to translate French in Italian so I click, in the from list, French, and I get
French -> English
Which is an undesirable state, for me, because I don't know how to do that. Especially if I were to select many languages, I'd get, inbetween 2 states I want to save, an indefinite amount of states I don't want to save.
If you still want to do so, you need to move the even listener from the button to the list(s), with the onchange event.
I'd also suggest you do your event binding trough jQuery, if you aren't already.
Hope this helped.

Working with Shopify Variants dropdown select

in my product template page i have this code:
<select name="id" id="ProductSelect-{{ section.id }}" class="product-single__variants">
I'm using a javascript snippet to hide variants based on the customers choices. I want to use one snippet file for all my products, but cannot get javascript to read the following:
var productSelect = "ProductSelect-{{ section.id }}";
how would i do this? My alternative is that i have a snippet file for each product which although possible, makes it long and arduous.
Any ideas would be appreciated.
The issue that you're running into is that {{ section.id }} is a template variable. In the rendered HTML, that part is replaced by the appropriate variable. Once your javascript runs, there will be no element on the page with double-curly-braces in any of its attributes.
There are a few ways that you might be able to get around this:
Idea 1: Store the section ID somewhere
To do this, you would need to have some place where you can associate section IDs with sections that have loaded on the page, tying that piece of data to something that your snippet already knows about when it runs.
If, say, your snippet knows the product handle of whatever product is being changed, you could add something like this inside the form:
<script>
// If our lookup object already exists, do nothing. Otherwise, initialize it as an empty object
window.section_lookup = window.section_lookup || {};
//Now save the section ID using the product's handle
//Using the json filter when we print Liquid variables to Javascript ensures that the resulting value is always Javascript-legal.
section_lookup[{{ product.handle | json}}] = {{ section.id | json }};
</script>
Now, in your lookup code, you can use:
// Assuming that you have a variable called product_handle already
var productSelect = "ProductSelect-" + section_lookup[product_handle];
Which will give you the specific ID that you're looking for.
Idea 2: Use the power of the form object
Is your code snippet running in some context where you know something about any of the elements that contain the select element you want? For example, do you already know the form or the product-area wrapper?
If you have the form that contains your select box, you're golden. Every form knows the names of all of the form-fields contained inside it. Since the field's name is id, getting to the right select box from the form object is as easy as:
// Assuming you have a variable named form representing the correct form, access the form field with the name 'id'
var idField = form['id'];
NOTE: If your form is jQuery-selected, you probably won't have that ability. Fortunately, if you're stuck with a jQuery-wrapped object you can easily un-wrap it like so:
// Assuming somebody gave you a variable named $form that they jQuery-selected....
var form = $form[0];
var idField = form['id'];
If you don't have the form but you do have quick access to any other input inside the form, you're also in luck - Every form element (ie: inputs, selects, textareas, fieldsets...) also knows what form it belongs to.
// Assuming that there is a variable named target which is a form element contained in the same form as the ID field that we want:
var form = target.form;
var idField = form['id'];
Idea 3: Use some other wrapping element to constrain your lookup
If you know anything about some wrapping element that contains the select box that you want and doesn't include the select box that you don't want, you can constrain your query-selector to only look inside the wrapper. That way, you'll only find the element that you need.
If you're using plain ol' "vanilla" Javascript:
//Assuming we have a variable named product_wrapper
var idField = product_wrapper.querySelector('[name="id"]');
Or if you prefer jQuery:
//Still assuming that we have a variable named product_wrapper
var idField = jQuery('[name="id"]', product_wrapper);
Hopefully you can find success with at least one of these methods. Good luck!

Qualtrics: Loop over embedded data fields?

I have a large set of embedded data fields that are called rnd1, rnd2, rnd3 etc. In a certain question block, I stored to each of these a certain value (each a different random number).
I also have a Loop and Merge question block, and in each round, I would like to access the stored data of a different field (i.e. in the 1st round I'd like to access whatever is in rnd1, in the 2nd round access rnd2 etc.) Can this be done in Qualtrics?
I tried something like:
Qualtrics.SurveyEngine.addOnload(function()
{
var trialNum = this.questionId.split('_')[0]; // getting the loop's current round number
var EDname = "rnd"+trialNum; // name of desired EF field
var rndNum = "${e://Field/" + EDname + "}"; // this is where I'd like stored the right ED value
// some more code that uses rndNum
});
but this does not work. It seems that while EDname gets the right string, I cannot access the value of that embedded field this way (though var rndNum = "${e://Field/rnd1} does work and returns the right value, so the problem seems to be in the looping strucutre).
If I cannot loop over the different fields in the JS code for some reason, is there another clever way to get that done in Qualtrics? For example, I thought it may be possible to use the different field names in the Loop and Merge section as "Field 2", but this seem to require me setting manually each and every ED field name.
Thanks.
Piped embedded data fields are resolved on the server before the page gets sent to your browser. So, it is impossible to dynamically create an embedded data field name and resolve it on the client side with JavaScript.
The way you are doing it with a loop & merge field is the best way.

Pass form field values to parameters of a portlet:renderURL tag in WebSphere Portal 6.1

I'm developing a portlet for WebSphere Portal 6.1, with JSP/JSTL, pure javascript, no AJAX frameworks, with a JSP that shows a send feedback form and, when submitted, redirects to another JSP to show the user the success of the operation.
I use javascript to get the values of the form fields by using document.getElementById() function. For example:
var valorAsunto = document.getElementById("asunto").value;
where "asunto" is the ID of a text field in my form. Also my form has the following structure:
<form name="formularioCorreo" id="formularioCorreo" method="post" action="<portlet:renderURL><portlet:param name="nextTask" value="sendFeedback"/></portlet:renderURL>">
That works OK, but I'm having trouble when trying to build the <portlet:renderURL> tag from that javascript values: when I try to concatenate a string for the renderURL and then reassign to form action like this:
var valorAction = '<portlet:renderURL><portlet:param name="nextTask" value="sendFeedback"/><portlet:param name="asunto" value="'+valorAsunto+'"/></portlet:renderURL>';
document.formularioCorreo.action = valorAction;
document.formularioCorreo.submit();
The resulting string, when application is deployed, has the structure:
/wps/myportal/<portletpath>/!ut/p/c5/<a very long random sequence of
numbers and letters>/
So one can't figure out where the parameter values are, but if I print the assigned values it shows something like:
asunto: '+valorAsunto+'
instead of
asunto: this is a sample subject
I've been trying to use some other ways to concatenate the string; for instance with a StringBuffer, as shown on http://www.java2s.com/Tutorial/JavaScript/0120__String/StringBufferbasedonarray.htm
and also javascript functions like encodeURI()/decodeURI(), replace(), etc. but I just can't get either the URL with the right parameter values or the URL encoded in the structure shown above (the one with the long sequence of chars).
Sometimes I manage to get the right parameter values, by manually replacing in the valorAction assignation all the "<" for "<" and all the ">" for ">" before the concatenation, and then doing the following:
var valorAction = valorAction.replace(/</g,"<").replace(/>/g,">");
Then I get the following string:
<portlet:renderURL><portlet:param name="nextTask" value="sendFeedback"/><portlet:param name="asunto" value="this is a sample subject"/></portlet:renderURL>
which is OK, but when it has to redirect to the results page it shows an error like this
Error 404: EJPEI0088E: The resource <portlet:renderURL><portlet:param
name="nextTask" value="sendFeedback"/><portlet:param name="asunto"
value="this is a sample subject"/></portlet:renderURL> could not be
found.
Does someone know how to transform that string to the right format to be rendered?
Does someone know any other way to "inject" that parameter values to the renderURL?
I'd like to know also if it is possible to pass that parameter values from javascript to JSP so I could put that values in a HashMap of parameters to use with the PortletURLHelper.generateSinglePortletRenderURL() method, in case the former is not possible.
Thank you.
Update 1:
In my doView() I use the following, in order to make the redirection:
String targetJsp = "/_Feedback/jsp/html/FeedbackPortletView.jsp";
String nextTask = request.getParameter("nextTask");
//(... I have omitted code to conditionally select targetJsp value, according to nextTask value ...)
PortletRequestDispatcher rd = getPortletContext().getRequestDispatcher(targetJsp);
rd.include(request, response);
This is just a new JSP inside my portlet, not a different portal page. I do use request.getParameter() to get the values for my form fields from my doview():
String subjectFeedback = request.getParameter("asunto");
String bodyFeedback = request.getParameter("mensaje");
String emailFeedback = request.getParameter("emailFeedback");
I don't see the need to include hidden fields if my form has the fields named above. In fact, what I'm trying to do is to pass the values the user entered in these fields as request parameters, but the values I get by this means are the following:
subjectFeedback: "'+valorAsunto+'"
bodyFeedback: "'+valorMensaje+'"
emailFeedback: "'+valorEmailFeedback+'"
I get the above values when using concatenation by "+"; when I use StringBuffer I get the following values:
subjectFeedback: "'); buffer.append(valorAsunto); buffer.append('"
bodyFeedback: "'); buffer.append(valorMensaje); buffer.append('"
emailFeedback: "'); buffer.append(valorEmailFeedback); buffer.append('"
Does someone know any other way to "inject" that parameter values to the renderURL?
There are two IBM guides on that topic.
Portal 6.1 and 7.0 Advanced URL Generation Helper classes
How to create a link to a portlet (Standard API) that passes parameters to that portlet
How are you redirecting to the other page? Is it a different portal page or just a new JSP page inside your portlet?
You don't need to inject any parameters to the render URL. Have a form whose action targets to a renderURL. Now to pass information to your portlet's doView() method, you can have hidden fields in the form ,then populate them using JavaScript and then submit the form. In the doView() method, you can use request.getParameter() to get the parameters.
Well, sometimes the most obvious things happen to be the way to the solutions.
I was too busy trying to find elaborated causes for that situation that I did not checked for this at all:
My form fields were correctly identified by different id, but they weren't set their name properties.
With the help of a work partner we could figure out that, so assigning the same value of id for name on each form field did the trick.
So, I ended up skipping that reassigning action thing, because the field values are being set as request parameters, as it should be.
Thanks for the help.

Dynamically Add JS to an ASP.NET page and get results from the JS

Here's my issue:
Client(s) give me separate JS files which will run a check of some sort on the user's system (Browser type, are cookies enabled?, etc.) and a list of acceptable values to be returned from this check.
I want to run through each JS file when a user visits the site and compare the results to the list of acceptable values, then alert the user if they pass these requirements or not.
I'm currently using RegisterClientScriptBlock() to add the JS to the client's page, so it's being run, but I'm having issues getting the result value from the JS back to ASP.NET in order to do the comparison.
I've tried using hidden fields that the JS will dump the value to and ASP.NET will read from, but I'm having difficulty generating the hidden fields on demand (since I have no idea how many Js files the client could have) and have them work in the ASP.NET code.
Any help, or suggestions in the right direction would be awesome, thanks!
What I would do is have the results be an array of KeyValuePair objects that you would then serialize to JSON. So you create the javascript object type like so:
function KeyValuePair(key, value){
this.Key = key;
this.Value = value;
}
Then you would build up an array of KeyValuePairs like so:
//This array is declared in the global scope
var ValueArray = new Array();
function someFunction(){
//this assumes that the key and value variables are created earlier in the function
var valueToStore = new KeyValuePair(key, value);
ValueArray[ValueArray.length] = valueToStore;
}
So at the point when you are done with all your checks you would use the json2 serializer to serialize the array to json for storage in your hidden field.
var jsonToSaveToHiddenField = JSON.stringify(ValueArray);
//Logic to store resulting json and trigger the serverside evaluation here
On the server side you would use JavascriptSerializer to deserialize your json to an array of KeyValuePairs. Here is the msdn doc on that: JavaScriptSerializer Class Reference
So with this approach you only need one hidden field. So you don't need to dynamically create it which should simplify the server side retrieval quite a bit.
The above should work with minimal changes however I haven't run this through a compiler so there might be some minor syntax errors preset.

Categories