I have a JSON object and when i alert it i get this:
and i want to get this:
function getNameById(id){
return usersArray.find(item => item.id === id).name;
}
var usersArray = [
{"id":"135","name":"Jenny"},
{"id":"162","name":"Kelly"}
];
$("#submit").click(function (e) {
var errors = {};
$(".validation").each(function(){
var worker_id = $(this).attr('id').replace(/[^\d]/g, '');
var w_name = getNameById(worker_id);
if(!errors[w_name]) errors[w_name] = [];
if ( $(this).val() == "" ) {
errors[w_name].push( $(this).attr('id').replace(/[^a-zA-Z]/g, '') + " must be filled!");
//errors[w_name].push("second number must be smaller than first");
}
if ( $(this).attr('id') == "second-"+worker_id && ($(this).val() > $('#first-'+worker_id+'').val())) {
errors[w_name].push("second number must be smaller than first");
}
});
alert(JSON.stringify(errors, null, 2));
e.preventDefault();
e.stopPropagation();
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<form method="post">
First<input id="first-135" class="validation" name="first" type="text" value="5"><br>
Second<input id="second-135" class="validation" name="second" type="text" value="8"><br>
Signature<input id="signature-135" class="validation" name="signature" type="text"><br>
<input id="submit" type="submit" value="Submit">
</form>
How can i achieve that?
Transform your object to a string like this
let obj = {
"Jenny" : [
"Second number must be smaller than first",
"Signature must be filled !"
]
};
let str = "";
Object.keys(obj).forEach(k => {
str += k + ":\n";
str += obj[k].join(",\n");
});
console.log(str);
Extract the data from the JSON data that you have in errors instead of running JSON.stringify directly. You should be able to get the data like this: errors["Jenny"] to get a list of the errors. Then combine them into a string according to your liking.
I honestly don't think your question has absolutely anything to do with JSON. The only reason why some JSON even shows up is because you're generating it for the alert():
alert(JSON.stringify(errors, null, 2));
// ^^^^^^^^^^^^^^ This generates JSON
If you want to concatenate some array items you can use a combination of the concatenation operator (+) and Array.join():
alert(w_name + ":\n" + errors[w_name].join(",\n"));
Tweak format to your liking.
var w_name = "Jenny";
var errors = {};
errors[w_name] = [];
errors[w_name].push("Second number must be smaller than first");
errors[w_name].push("Signature must be filled!");
alert(w_name + ":\n" + errors[w_name].join(",\n"));
Related
I have asked this question one time but couldn't get any proper answer.So making the question simpler.Im using codeigniter
javascript function in view file
here the abc output looks like this
0:{a:'1',b:'2',c:'35'}
1:{a:'2',b:'3',c:'34'}
2:{a:'5',b:'1',c:'87'}
3:{a:'4',b:'3',c:'90'}
function test()
{
const show_div = document.getElementById('div_show');
const abc =[];
abc.push({a,b,c});
for (const data of abc){
const values = Object.values(data);
for (const value of values){
const input = document.createElement(
'<input type="text" name="a[]" value=" '+ value[0]+ ' " required>' +
'<input type="text" name="b[]" value=" '+ value[1]+ ' " required>' +
'<input type="text" name="c[]" value=" '+ value[2] + ' " required>'
);
input.innerText = value ;
show_div .appendChild(
input
);
}
}
}
I need to get this to the view
<form>
//there are more divs here
<div id='div_show'>
//need output like this
// 1 2 35
// 2 3 34
// 5 1 87
// 4 3 90
</div>
</form>
And then I want to pass a,b,c data to model
How can I get this data.Actually im creating this view output just pass the data in post method because in form submit its passing the data through action url without ajax.
You can try like this. You can add any input field with the array of object data.
I have separated each array item with a div so that you can design it with css or you can remove it if you don't need the div.
const data = [{a:'1',b:'2',c:'35'},
{a:'2',b:'3',c:'34'},
{a:'5',b:'1',c:'87'},
{a:'4',b:'3',c:'90'}];
function show() {
const container = document.getElementById("div_show");
let fields = '';
for(item of data) {
fields += '<div class="field_row">';
Object.keys(item).forEach( key => {
fields += `<input type="text" name="${key}[]" value="${item[key]}" required>`
})
fields += '</div>';
}
container.innerHTML = fields;
}
show()
<form><div id="div_show"></div></form>
Kind of ES6 way
const data = [{a:'1',b:'2',c:'35'},{a:'2',b:'3',c:'34'},{a:'5',b:'1',c:'87'},{a:'4',b:'3',c:'90'}];
function show() {
const fields = data.map((obj) => {
const row = Object.entries(obj)
.map(([key, value]) =>`<input type="text" name="${key}-${value}" value="${value}">`)
.join('');
return `<div>${row}</div>`;
}).join('');
document.getElementById("div_show").innerHTML = fields;
}
show();
<form><div id="div_show"></div></form>
Can you please provide more specific details your exact output?
If you need just 3 input elements in side that div(#div_show), your inner loop is redundant, you can eliminate it and it would give you what you need.
I have a javascript OnChange function on a column having textboxes which captures the name of each row in a column. I am appending all the names and storing in variable.
Now , suppose user clicks same textbox again , I don't want to append that name again.
var AppendedString = null;
function onChangeTest(textbox) {
AppendedString = AppendedString;
AppendedString = AppendedString + ';' + textbox.name;
// this gives null;txt_2_4;txt_2_6;txt_3_4;txt_2_4 and so on..and I don't want to append same name again , here it's txt_2_4
}
My Input text :
<input type="text" name="txt_<%=l_profileid %>_<%=l_processstepsequence%>" value="<%= l_comments%>" onfocus="this.oldvalue = this.value;" onchange="onChangeTest(this);this.oldvalue = this.value;">
Those rows seem to have unique names.
you can simply check if AppendedString already contains that name :
var AppendedString=''
function onChangeTest(textbox) {
if (!AppendedString.includes(textbox.name)) {
AppendedString += ';' + textbox.name;
}
}
Codepen Link
You can’t initialize AppendedString as null otherwise, the includes() method won’t be available
otherwise, you can give each row a unique ID, and store in an array IDs that already have been clicked by the user.
var AppendedString = '';
var clickedRows = [];
function onChangeTest(textbox) {
if (!clickedRows.includes(textbox.id)) {
AppendedString += ';' + textbox.name;
clickedRows.push(textbox.id)
}
}
var arr = [];
$("input[type='text']").on("click", function() {
var nowS = ($(this).attr('name'));
if (!(arr.indexOf(nowS) > -1)) {
arr.push(nowS)
}
console.log(arr)
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<input type="text" id="m1" name="lbl1">
<input type="text" id="m2" name="lbl2">
<input type="text" id="m3" name="lbl3">
Somewhat similar to your need,
var arr = [];
$("input[type='text']").on("click", function() {
var nowS = ($(this).attr('name'));
if (!arr.includes(nowS)) {
arr.push(nowS)
}
console.log(arr)
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<input type="text" id="m1" name="lbl1">
<input type="text" id="m2" name="lbl2">
<input type="text" id="m3" name="lbl3">
You can add flag your textboxes and ignore if it's clicked again. Like using jquery you can do something like this:
function onChangeTest(textbox) {
AppendedString = AppendedString;
if (!textbox.hasClass("clicked")){
AppendedString = AppendedString + ';' + textbox.name;
textbox.AddClass("clicked");
}
}
I have a Contact Form that utilizes Google Scripts. It successfully sends the email and formats it decently to my inbox, but there are 2 problems:
-I need it so that IF var key is equal to 'Action', then do not display it in the email it sends. Because right now, "Action send_message" is getting included in the email and I don't like that.
For this, I have unsuccessfully tried things like:
for (var idx in order) {
var key = order[idx];
//Skip this entry into the email output if it is the Action
if( key === 'Action') {
continue
}
It seems to not react to this code at all.
-I also need it so that if a city is selected, e.g. Alachua, that the email says 'Alachua' instead of 'Florida_Alachua'. But I can't add a NAME to an option since apparently options don't have that property. I also can't do the quick fix of changing the VALUE of the <option> to resolve this step, because of other code I have that conflicts with this route.
Google Scripts Code:
/******************************************************************************
* This tutorial is based on the work of Martin Hawksey twitter.com/mhawksey *
* But has been simplified and cleaned up to make it more beginner friendly *
* All credit still goes to Martin and any issues/complaints/questions to me. *
******************************************************************************/
// if you want to store your email server-side (hidden), uncomment the next line
var TO_ADDRESS = "myemail#email.com";
// spit out all the keys/values from the form in HTML for email
// uses an array of keys if provided or the object to determine field order
function formatMailBody(obj, order) {
var result = "";
if (!order) {
order = Object.keys(obj);
}
// loop over all keys in the ordered form data
for (var idx in order) {
var key = order[idx];
result += "<h4 style='text-transform: capitalize; margin-bottom: 0'>" + key + "</h4><div>" + sanitizeInput(obj[key]) + "</div>";
// for every key, concatenate an `<h4 />`/`<div />` pairing of the key name and its value,
// and append it to the `result` string created at the start.
}
return result; // once the looping is done, `result` will be one long string to put in the email body
}
// sanitize content from the user - trust no one
// ref: https://developers.google.com/apps-script/reference/html/html-output#appendUntrusted(String)
function sanitizeInput(rawInput) {
var placeholder = HtmlService.createHtmlOutput(" ");
placeholder.appendUntrusted(rawInput);
return placeholder.getContent();
}
function doPost(e) {
try {
Logger.log(e); // the Google Script version of console.log see: Class Logger
record_data(e);
// shorter name for form data
var mailData = e.parameters;
// names and order of form elements (if set)
var orderParameter = e.parameters.formDataNameOrder;
var dataOrder;
if (orderParameter) {
dataOrder = JSON.parse(orderParameter);
}
// determine recepient of the email
// if you have your email uncommented above, it uses that `TO_ADDRESS`
// otherwise, it defaults to the email provided by the form's data attribute
var sendEmailTo = (typeof TO_ADDRESS !== "undefined") ? TO_ADDRESS : mailData.formGoogleSendEmail;
// send email if to address is set
if (sendEmailTo) {
MailApp.sendEmail({
to: String(sendEmailTo),
subject: "Contact form submitted",
// replyTo: String(mailData.email), // This is optional and reliant on your form actually collecting a field named `email`
htmlBody: formatMailBody(mailData, dataOrder)
});
}
return ContentService // return json success results
.createTextOutput(
JSON.stringify({"result":"success",
"data": JSON.stringify(e.parameters) }))
.setMimeType(ContentService.MimeType.JSON);
} catch(error) { // if error return this
Logger.log(error);
return ContentService
.createTextOutput(JSON.stringify({"result":"error", "error": error}))
.setMimeType(ContentService.MimeType.JSON);
}
}
/**
* record_data inserts the data received from the html form submission
* e is the data received from the POST
*/
function record_data(e) {
var lock = LockService.getDocumentLock();
lock.waitLock(30000); // hold off up to 30 sec to avoid concurrent writing
try {
Logger.log(JSON.stringify(e)); // log the POST data in case we need to debug it
// select the 'responses' sheet by default
var doc = SpreadsheetApp.getActiveSpreadsheet();
var sheetName = e.parameters.formGoogleSheetName || "responses";
var sheet = doc.getSheetByName(sheetName);
var oldHeader = sheet.getRange(1, 1, 1, sheet.getLastColumn()).getValues()[0];
var newHeader = oldHeader.slice();
var fieldsFromForm = getDataColumns(e.parameters);
var row = [new Date()]; // first element in the row should always be a timestamp
// loop through the header columns
for (var i = 1; i < oldHeader.length; i++) { // start at 1 to avoid Timestamp column
var field = oldHeader[i];
var output = getFieldFromData(field, e.parameters);
row.push(output);
// mark as stored by removing from form fields
var formIndex = fieldsFromForm.indexOf(field);
if (formIndex > -1) {
fieldsFromForm.splice(formIndex, 1);
}
}
// set any new fields in our form
for (var i = 0; i < fieldsFromForm.length; i++) {
var field = fieldsFromForm[i];
var output = getFieldFromData(field, e.parameters);
row.push(output);
newHeader.push(field);
}
// more efficient to set values as [][] array than individually
var nextRow = sheet.getLastRow() + 1; // get next row
sheet.getRange(nextRow, 1, 1, row.length).setValues([row]);
// update header row with any new data
if (newHeader.length > oldHeader.length) {
sheet.getRange(1, 1, 1, newHeader.length).setValues([newHeader]);
}
}
catch(error) {
Logger.log(error);
}
finally {
lock.releaseLock();
return;
}
}
function getDataColumns(data) {
return Object.keys(data).filter(function(column) {
return !(column === 'formDataNameOrder' || column === 'formGoogleSheetName' || column === 'formGoogleSendEmail' || column === 'honeypot');
});
}
function getFieldFromData(field, data) {
var values = data[field] || '';
var output = values.join ? values.join(', ') : values;
return output;
}
Contact Form HTML
<section id="contact-form">
<form id="gform"
class="contact-form" method="post"
action="(Google Scripts URL)"
enctype="text/plain">
<p>
<label for="name">Your Name <font face="Arial" color="red">*</font></label>
<input type="text" style="height:35px;" class="heighttext required" name="name" id="name" class="required" title="* Please provide your name">
</p>
<p>
<label>Your Location <font face="Arial" color="red">*</font></label>
<select name="Location" id="column_select" style="height:35px;" class="required" title=" * Please provide your location">
<option selected value="col00">-- State --</option>
<option value="Alabama">Alabama</option>
<option value="California">California</option>
<option value="Florida">Florida</option>
</select>
<select name="City" id="layout_select" style="height:35px;">
<option disabled selected value="Florida">-- City --</option>
<option name="Alachua" value="Florida_Alachua">Alachua</option>
<option name="Alford" value="Florida_Alford">Alford</option>
</select>
</p>
<p>
<input type="submit" value="Send Message" id="submit" class="pp-btn special">
<img src="images/ajax-loader.gif" id="contact-loader" alt="Loading...">
<input type="hidden" name="action" value="send_message">
</p>
</form>
</section><!-- #contact-form -->
Form Handler Javascript
(function() {
function validEmail(email) { // see:
var re = /^([\w-]+(?:\.[\w-]+)*)#((?:[\w-]+\.)*\w[\w-]{0,66})\.([a-z]{2,6}(?:\.[a-z]{2})?)$/i;
return re.test(email);
}
function validateHuman(honeypot) {
if (honeypot) { //if hidden form filled up
console.log("Robot Detected!");
return true;
} else {
console.log("Welcome Human!");
}
}
// get all data in form and return object
function getFormData() {
var form = document.getElementById("gform");
var elements = form.elements;
var fields = Object.keys(elements).filter(function(k) {
return (elements[k].name !== "honeypot");
}).map(function(k) {
if(elements[k].name !== undefined) {
return elements[k].name;
// special case for Edge's html collection
}else if(elements[k].length > 0){
return elements[k].item(0).name;
}
}).filter(function(item, pos, self) {
return self.indexOf(item) == pos && item;
});
var formData = {};
fields.forEach(function(name){
var element = elements[name];
// singular form elements just have one value
formData[name] = element.value;
// when our element has multiple items, get their values
if (element.length) {
var data = [];
for (var i = 0; i < element.length; i++) {
var item = element.item(i);
if (item.checked || item.selected) {
data.push(item.value);
}
}
formData[name] = data.join(', ');
}
});
// add form-specific values into the data
formData.formDataNameOrder = JSON.stringify(fields);
formData.formGoogleSheetName = form.dataset.sheet || "responses"; // default sheet name
formData.formGoogleSendEmail = form.dataset.email || ""; // no email by default
console.log(formData);
return formData;
}
function handleFormSubmit(event) { // handles form submit without any jquery
event.preventDefault(); // we are submitting via xhr below
var data = getFormData(); // get the values submitted in the form
/* OPTION: Remove this comment to enable SPAM prevention, see README.md
if (validateHuman(data.honeypot)) { //if form is filled, form will not be submitted
return false;
}
*/
if( data.email && !validEmail(data.email) ) { // if email is not valid show error
var invalidEmail = document.getElementById("email-invalid");
if (invalidEmail) {
invalidEmail.style.display = "block";
return false;
}
} else {
disableAllButtons(event.target);
var url = event.target.action; //
var xhr = new XMLHttpRequest();
xhr.open('POST', url);
// xhr.withCredentials = true;
xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
xhr.onreadystatechange = function() {
console.log( xhr.status, xhr.statusText )
console.log(xhr.responseText);
//document.getElementById("gform").style.display = "none"; // hide form
/*
var thankYouMessage = document.getElementById("thankyou_message");
if (thankYouMessage) {
thankYouMessage.style.display = "block";
}
*/
return;
};
// url encode form data for sending as post data
var encoded = Object.keys(data).map(function(k) {
return encodeURIComponent(k) + "=" + encodeURIComponent(data[k])
}).join('&')
xhr.send(encoded);
}
}
function loaded() {
console.log("Contact form submission handler loaded successfully.");
// bind to the submit event of our form
var form = document.getElementById("gform");
form.addEventListener("submit", handleFormSubmit, false);
};
document.addEventListener("DOMContentLoaded", loaded, false);
function disableAllButtons(form) {
var buttons = form.querySelectorAll("button");
for (var i = 0; i < buttons.length; i++) {
buttons[i].disabled = true;
}
}
})();
finally, this is the extra code that would break if I simply tried changing the value of option to, e.g., 'Alachua' instead of 'Flordia_Alachua'. https://jsfiddle.net/hmatt843/504dgmqy/19/
Thanks for any and all help.
Try console.log(key) before if( key === 'Action'). I think you'll find that key never equals 'Action', exactly. Looks like you'll need if( key === 'action'), instead.
If you wish to remove part of string value, try the replace method: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/replace
It also looks like you're trying to work with elements[k].name when you mean to be working with elements[k].value.
I believe your code should look something like...
function(k) {
if(elements[k].value !== undefined) {
return elements[k].value.replace('Florida_', '');
// special case for Edge's html collection
} else if(elements[k].length > 0){
return elements[k].item(0).value.replace('Florida_', '');
}
}
... or something to that effect.
In the future, you may want to make it easier for folks trying to help you by posting only the portions of code your having trouble with, and breaking your questions into different posts. A lot to sift through up there.
Hope this helped.
The split() method splits a String object into an array of strings by separating the string into substrings, using a specified separator string to determine where to make each split.
Var splitValue = elements[k].item(0).value.split("");
splitValue[1] will give you a string of characters after the delimeter () in this case.
I have the following JavaScript which build url paramters based on users input:-
$(document).ready(function(){
$('#button').click(function(e) {
var count=1;
var s="";
var inputvalue = $("#journal").val();
var inputvalue2 = $("#keywords").val();
var inputvalue3 = $("#datepub").val();
var inputvalue4 = $("#title").val();
var inputvalue5 = $("#localcurrency").val();
var inputvalue6 = $("#locations").val();
var inputvalue7 = $("#dropdown1").val();
var inputvalue8 = $("#dropdown2").val();
if(inputvalue!=null && inputvalue!="")
{
s = s+ "FilterField"+count+"=Journal&FilterValue"+count+"="+inputvalue+"&";
count++;
}
if(inputvalue2!=null && inputvalue2!="")
{
s = s+ "FilterField"+count+"=KeyWords&FilterValue"+count+"="+inputvalue2+"&";
count++;
}
if(inputvalue3!=null && inputvalue3!="")
{
s = s+ "FilterField"+count+"=datepub&FilterValue"+count+"="+inputvalue3+"&";
count++;
}
if(inputvalue4!=null && inputvalue4!="")
{
s = s+ "FilterField"+count+"=Title&FilterValue"+count+"="+inputvalue4+"&";
count++;
}
if(inputvalue5!=null && inputvalue5!="")
{
s = s+ "FilterField"+count+"=localcurrency&FilterValue"+count+"="+inputvalue5+"&";
count++;
}
if(inputvalue6!=null && inputvalue6!="")
{
s = s+ "FilterField"+count+"=locations&FilterValue"+count+"="+inputvalue6+"&";
count++;
}
if(inputvalue7!=null && inputvalue7!="")
{
s = s+ "FilterField"+count+"=dropdown1&FilterValue"+count+"="+inputvalue7+"&";
count++;
}
if(inputvalue8!=null && inputvalue8!="")
{
s = s+ "FilterField"+count+"=dropdown2&FilterValue"+count+"="+inputvalue8+"&";
count++;
}
window.location.replace("/teamsites/Bib%20Test/Forms/search.aspx?"+s);
});
});
</script>
now the above script will generate URLs such as
http://***/teamsites/Bib%20Test/Forms/search.aspx?FilterField1=Journal&FilterValue1=123
http://***/teamsites/Bib%20Test/Forms/search.aspx?FilterField1=Journal&FilterValue1=123&FilterField2=localcurrency&FilterValue2=USD&
and thing were working well, till i tried passing a search parameter which contain &. for example i wanted to search for a record which have their journal = General&Procedure, so using my above code, the URL will be as follow:-
http://***/teamsites/Bib%20Test/Forms/search.aspx?FilterField1=Journal&FilterValue1=General&Procedure&
and i did not get any result,, as the application assume that the Procudure is a parameter and not part of the FilterValue1.. now to fix this specific problem, i define to build the URL parameters with encodeURIComponent() function as follow:-
var inputvalue = encodeURIComponent($("#journal").val());
var inputvalue2 = encodeURIComponent($("#keywords").val());
var inputvalue3 = encodeURIComponent($("#datepub").val());
var inputvalue4 = encodeURIComponent($("#title").val());
var inputvalue5 = encodeURIComponent($("#localcurrency").val());
var inputvalue6 = encodeURIComponent($("#locations").val());
var inputvalue7 = encodeURIComponent($("#dropdown1").val());
var inputvalue8 = encodeURIComponent($("#dropdown2").val());
now the generated URL will be as follow:-
http://***teamsites/Bib%20Test/Forms/search.aspx?FilterField1=Journal&FilterValue1=General%26Procedure
and i got the expected results..
but not sure if using encodeURIComponent() to only encode the parameter values is a valid fix,, as seems i will be encoding the & if it is part of the query string parameter,, but still the url contain non-encoded & which separate the url parameters .. now the result i got from the last url is correct.. but not sure if i am doing things correctly ? and is there a built-in function to do this work for me ??
Thanks
Here are sources for URL syntax:
Easily understandable and authoritative enough:
Components: https://en.wikipedia.org/wiki/Uniform_Resource_Identifier#Syntax
Query component: https://en.wikipedia.org/wiki/Query_string
Percent-encoding of non-allowed characters: https://en.wikipedia.org/wiki/Percent-encoding
Uniform Resource Identifier (URI): Generic Syntax (RFC 3986) https://www.rfc-editor.org/rfc/rfc3986
Components: https://www.rfc-editor.org/rfc/rfc3986#section-3
Query component: https://www.rfc-editor.org/rfc/rfc3986#section-3.4
Percent-encoding: https://www.rfc-editor.org/rfc/rfc3986#section-2.1
You will notice that the exact content of the query component is not standardized. Its simple definition is:
The query component is indicated by the first question
mark ("?") character and terminated by a number sign ("#") character
or by the end of the URI.
However, the de-facto standard is to use ampersand (&) character as delimiter. With this convention, anytime this character also appears in your data and is not meant to be a delimiter, you have to "percent-encode" it, as per the standard as well:
A percent-encoding mechanism is used to represent a data octet in a component when that octet's corresponding character is outside the allowed set or is being used as a delimiter of, or within, the
component.
You will easily understand that other special characters, like =, % and # must also be percent-encoded, should they appear in your data. There is no harm in encoding even more special characters as well.
Therefore if you follow this convention, your query component should be of the form:
?field1=value1&field2=value2
with each field and value being percent-encoded. In JavaScript, you can indeed conveniently use the encodeURIComponent function. Do not forget to encode the fields as well!
Furthermore, as your use case is very common, there are plenty libraries available that can handle such conversion for you, e.g. URI.js.
But since you mention using jQuery, you can conveniently use jQuery.param to do the conversion:
Create a serialized representation of an array, a plain object, or a jQuery object suitable for use in a URL query string or Ajax request. In case a jQuery object is passed, it should contain input elements with name/value properties.
$(document).ready(function() {
$('#button').click(retrieveInputsValues);
retrieveInputsValues();
});
function retrieveInputsValues() {
var inputIds = [
'Journal',
'KeyWords',
'datepub',
'Title',
'localcurrency',
'locations',
'dropdown1',
'dropdown2'
];
var obj = {};
var count = 1;
var value;
for (var i = 0; i < inputIds.length; i += 1) {
value = $('#' + inputIds[i].toLowerCase()).val();
if (value !== null && value !== '') {
obj['FilterField' + count] = inputIds[i];
obj['FilterValue' + count] = value;
count += 1;
}
}
console.log($.param(obj));
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.0.0/jquery.min.js"></script>
Journal
<input type="text" id="journal" value="test & ampersand, comma, % percent, = equal and space" />
<br />keywords <input type="text" id="keywords" />
<br />datepub
<select id="datepub">
<option value=""></option>
<option value="1950">1950</option>
<option value="2010">2010</option>
<option value="2017" selected>2017</option>
<option value="audi">Audi</option>
</select>
<br />title
<select id="title">
<option value=""></option>
<option value="TestDoc">test doc</option>
<option value="t">t</option>
</select>
<br />localcurrency
<select id="localcurrency">
<option value=""></option>
<option value="USD">USD</option>
</select>
<br />locations
<select id="locations">
<option value=""></option>
<option value="US">US</option>
<option value="UK">UK</option>
</select>
<br />dropdown1
<select id="dropdown1">
<option value=""></option>
<option value="a">a</option>
<option value="b">b</option>
</select>
<br />dropdown2
<select id="dropdown2">
<option value=""></option>
<option value="aa">aa</option>
<option value="bb">bb</option>
<option value="cc">cc</option>
<option value="dd">dd</option>
</select>
<br />
<button type="button" id="button">search</button>
<!-- re-used from https://stackoverflow.com/a/47008115/5108796 -->
BTW, usually there is no need to pass the field names as values, just "field=value" is used.
But you may have specific use case for your back-end processing?
Extending my comment as an answer.
Using encodeURIComponent is not only valid and correct, it is actually the only fix for supporting special characters in values in URL which have special meaning for a URL.
Encoding the values in URL component is important for prevent XSS attacks as well. Have a look here
URL-escaping is susceptible to double-escaping, meaning you must
URL-escape its parts exactly once. It is best to perform the
URL-escaping at the time the URL is being assembled.
However, you can improve your code in the following manner
var inputs = [ "#journal", "#keywords", "#datepub", "#title", "#localcurrency", "#locations", "#dropdown1", "#dropdown2" ];
$(document).ready(function(){
$('#button').click(function(e) {
var count = 1;
var searchParams = inputs.filter( function( id ){
return $( "#" + id ).val().trim().length > 0;
}).map( function( id ){
var value = encodeURIComponent( $( "#" + id ).val().trim() );
return "FilterField" + (count) + "=" + id + "&FilterValue" + (count++) + "=" + value;
}).join( "&" );
window.location.replace("/teamsites/Bib%20Test/Forms/search.aspx?"+ searchParams );
});
});
Alternatively, you can also use URL (though not supported in IE)
var inputs = [ "#journal", "#keywords", "#datepub", "#title", "#localcurrency", "#locations", "#dropdown1", "#dropdown2" ];
$(document).ready(function(){
$('#button').click(function(e) {
var count = 1;
var url = new URL( "/teamsites/Bib%20Test/Forms/search.aspx?", window.location.origin );
inputs.forEach( function( id ){
var value = encodeURIComponent( $( "#" + id ).val().trim() );
if ( value.length > 0 )
{
url.searchParams.append( "FilterField" + count, id );
url.searchParams.append( "FilterValue" + (count++), value );
}
});
window.location.replace( url.href );
});
});
As you can see that in this approach as well, you will have to use encodeURIcomponent since as per spec
The append(name, value) method, when invoked, must run these steps:
Append a new name-value pair whose name is name and value is value, to
list.
Run the update steps.
there is no guarantee that encoding will be done. So, the explicit encoding necessary!!.
/!\ THIS IS NOT AN ANSWER
In relation with comments
const [
$("#journal").val(),
$("#keywords").val(),
$("#datepub").val(),
$("#title").val(),
// ...
].forEach((x) => {
if (x !== null && x !== '') {
s += ...;
count += 1;
}
});
I use encodeUriComponent for this.
url += "&filter=" + encodeURIComponent(filter);
You want '&' inside the parameter value to be encoded, so you use 'encodeURIComponent' on the value of the parameter, but you don't want to encode the stuff between parameters.
Use this if you are not concerned about Internet Explorer or Edge.
I would recommend to use browser's URL API instead. It is stable and is available in most of the modern browsers to deal with URL specific work natively.
Your code can be changed as follows to use this API. It automatically encodes all the required parameters as per the specs. You don't need to deal with the query parameters manually.
$(document).ready(function() {
$('#button').click(function(e) {
var count = 1;
var s = "";
var url = new URL("http://yourhost.com/teamsites/Bib%20Test/Forms/search.aspx");
var inputvalue = $("#journal").val();
var inputvalue2 = $("#keywords").val();
var inputvalue3 = $("#datepub").val();
var inputvalue4 = $("#title").val();
var inputvalue5 = $("#localcurrency").val();
var inputvalue6 = $("#locations").val();
var inputvalue7 = $("#dropdown1").val();
var inputvalue8 = $("#dropdown2").val();
if (inputvalue != null && inputvalue != "") {
url.searchParams.set("FilterField" + count, "Journal");
url.searchParams.set("FilterValue" + count, inputvalue);
count++;
}
if (inputvalue2 != null && inputvalue2 != "") {
url.searchParams.set("FilterField" + count, "KeyWords");
url.searchParams.set("FilterValue" + count, inputvalue2);
count++;
}
if (inputvalue3 != null && inputvalue3 != "") {
url.searchParams.set("FilterField" + count, "datepub");
url.searchParams.set("FilterValue" + count, inputvalue3);
count++;
}
if (inputvalue4 != null && inputvalue4 != "") {
url.searchParams.set("FilterField" + count, "Title");
url.searchParams.set("FilterValue" + count, inputvalue4);
count++;
}
if (inputvalue5 != null && inputvalue5 != "") {
url.searchParams.set("FilterField" + count, "localcurrency");
url.searchParams.set("FilterValue" + count, inputvalue5);
count++;
}
if (inputvalue6 != null && inputvalue6 != "") {
url.searchParams.set("FilterField" + count, "locations");
url.searchParams.set("FilterValue" + count, inputvalue6);
count++;
}
if (inputvalue7 != null && inputvalue7 != "") {
url.searchParams.set("FilterField" + count, "dropdown1");
url.searchParams.set("FilterValue" + count, inputvalue7);
count++;
}
if (inputvalue8 != null && inputvalue8 != "") {
url.searchParams.set("FilterField" + count, "dropdown2");
url.searchParams.set("FilterValue" + count, inputvalue8);
count++;
}
window.location.replace(url.href);
});
});
In addition to it, I recommend to incorporate the suggestions from #GrégoryNEUT, as it makes the code concise and easy to read.
I am trying to build a custom control using HTML and JQuery. The control will display a text value. The user can enter a variety of key/value pairs. Currently, I have the following HTML
<input id="keyValue" type="text" />
<select id="keyName" name="keyName">
<option value="k1">Some Name</option>
<option value="key2">Another Name</option>
<option value="arg3">How about one more</option>
</select>
<input id="keyValuePairs" type="hidden" />
The value displayed in "keyValue" will change based on the option the user chooses. I'm trying to keep the mappings in keyValuePairs. In an attempt to do this, I have the following:
$('#keyName').on('change', function() {
var key = $('#keyName').val();
var keyValuePairs = $('#keyValuePairs').val();
if (keyValuePairs[key]) {
$('#keyValue').val(keyValuePairs[key]);
} else {
$('#keyValue').val('');
}
});
$('#keyValue').on('change', function() {
var key = $('#keyName').val();
var keyValuePairs = $('#keyValuePairs').val();
if (!keyValuePairs ) {
keyValuePairs = {};
}
keyValuePairs[key] = $(this).val();
$('#keyValuePairs').val(JSON.stringify(keyValuePairs));
});
For some reason, the text field always shows a blank string after I choose another key. I believe it has something to do with how I'm encoding or decoding the JSON. When I add console.log to the keyValuePairs I noticed that sometimes quotes are included and other times they're not. Yet, the code looks correct to me.
What am I doing wrong?
I believe you should JSON.parse $('#keyValuePairs').val() after you've read it (since you stringify the pairs when you set the value)
UPDATE:
You must also ensure that the value is not empty:
$('#keyName').on('change', function() {
var key = $('#keyName').val();
var val = $('#keyValuePairs').val();
if (val && val.length > 0) {
var keyValuePairs = JSON.parse(val);
if (keyValuePairs[key]) {
$('#keyValue').val(keyValuePairs[key]);
} else {
$('#keyValue').val('');
}
}
});
$('#keyValue').on('change', function() {
var key = $('#keyName').val();
var val = $('#keyValuePairs').val();
var keyValuePairs;
if (val && val.length > 0) {
keyValuePairs = JSON.parse(val);
} else {
keyValuePairs = {};
}
keyValuePairs[key] = $(this).val();
$('#keyValuePairs').val(JSON.stringify(keyValuePairs));
});
json_encode(#keyValuePairs) //encoding
json_decode(#keyValuePairs) //decoding
datatype : json