Reputation: 121
I am dynamically converting a list of options to a series of radio buttons. One of the values that is in the option has a literal quote mark.
<option value="6\" tall">
When I loop through each option, pull the a value $(this).val();
then I build a string for the radio button:
rb="input id=\"CTRL"+fld+"_"+cnt+"\" name=\""+fld+"\" type=\"radio\" "+ sel+" value=\"" +val+ "\"" +valCaption";
If I debug and break on this, the string is created correctly, but when I insert the element, the literal in the value is lost and the result is:
<input id="CTRLText1_3" name="Text1" type="radio" value="Rev 6" tall"="">
I cannot escape the value because then the value doesn't actually match what is being returned by the original select list.
Any ideas how I can create this radio button?
Upvotes: 0
Views: 2799
Reputation: 121
Thank you for everyone's suggestions. I did find the problem. I actually had to first collect the values from the options, then build the radio buttons with a blank value attribute and add that to the page. Then loop back through and just the $(fieldid).val(value) to set the values.
The other issue with saving the value then putting our page back into edit mode and the value not being re-selected. The ultimate problem is a bug in the core of the software where its not correctly comparing the stored value to the value in the list.
Upvotes: 0
Reputation: 44078
There's two easy ways to avoid conflicting quotes:
Instead of using double quotes in the HTML, use single quotes.
<option value='6" tall'>6" tall</option>
<option>
will default to its text content if value
is not assigned.
<option>7" tall</option>
The use of complex literal strings with concatenated variables are a little more manageable if you alternate between double and single quotes:
// Literal string concatenation syntax: '+VAR+'
let literalString = '<input id="'+ID+'" type="radio">';
Template literals interpolate variables and expressions:
// Template literal interpolation syntax: ${VAR}
let templateLiteral = `<input id="${ID}" type="radio">`;
I prefer the use of template literals for longer complex strings and literal strings for short simple strings.
The following demo collects all values into an array then creates a simple radio button then adds the attributes and values to it using simple JavaScript property assignment and the array of values. The use of htmlStrings is very error prone consider the alternative presented in demo.
Note: details are commented in demo
// Define counter
let i = 0;
// Delegate click event to button.add
$('.add').on('click', function(e) {
// Increment counter
i++;
/*
.map() will collect all .data and return their values
.get() will place all of the values into an array
V is an array of values
*/
let V = $('.data').map(function() {
return $(this).val();
}).get();
// Checking V array
console.log(JSON.stringify(V));
// Append a radio button to fieldset.box
$('.box').append(`<input type='radio'>`);
/*
- Reference the last radio button
- Dereference the last radio button from a jQuery Object
to a JavaScript DOM Node by suffixing [0] to it.
- The reason for dereferencing is to be able to use
simple plain JavaScript properties
*/
const rad = $('.box :radio:last')[0];
/*
Values are referenced by index from the V array
The attributes are set by property assignments
*/
rad.id = 'CTRL' + V[0] + '_' + i;
rad.name = V[0];
rad.value = V[1] + ' ' + V[2];
// Checking the radio button HTML
console.log(rad.outerHTML);
});
/*
This function just demonstrates what each radio button's
value is when rendered as HTML
*/
$('#formA').on('change', function(e) {
if ($(e.target).is(':checked')) {
$('#view').html($(e.target).val());
}
});
:root,
body {
font: 400 3vw/1.45 Consolas
}
select,
input,
button {
display: inline-block;
font: inherit;
height: 3ex;
line-height: 1;
width: 10ch;
margin-bottom: 8px;
padding: 0 2px;
vertical-align: middle
}
select {
padding: 2px 2px 4px 2px;
width: 12ch;
}
button {
padding: 0px 3px 5px;
line-height: 1.25;
width: 6ch;
cursor: pointer
}
#view {
color: tomato
}
<form id='formA'>
<input id='fld' class='data' value='Text1'>
<input id='val' class='data' value='Rev'>
<select id='valCaption' class='data'>
<option value='6" tall'>6" tall</option>
<option>7" tall</option>
</select>
<button class='add' type='button'>ADD</button>
<fieldset class='box'>
<output id='view'></output><br>
</fieldset>
</form>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
Upvotes: 0
Reputation: 121
More info: I tried building the radio buttons with an empty "value" attribute:
<input type="radio" value="">
The option tag actually looks like this:
<option value="6\" tall">
As I loop through my options I put the values into an array. Then after I add the HTML for the radio buttons to the page, I loop through the array and add the value to the attribute of the radio button.
for(x=0;x<arrVals.length; x++){
$("#CTRL"+fld+"_"+x).attr("value",arrVals[x]);
}
The end result, though is this:
<input id="CTRLText1_1" name="Text1" type="radio" value="Rev 6" tall">
The = sign has been escaped with """ While this is closer, it unfortunately is not the same. The original value in the option tag does not match the end-result value of the radio button.
Upvotes: 0
Reputation: 65845
In HTML \"
doesn't mean literal quote, it just means backslash followed by a double-quote. In HTML to produce a quote character when you need to, you use HTML Entities and the specific entity for a double quote is: "
.
<input value=""To be or not to be"">
\"
is the escape code for a double quote when that string is parsed by the JavaScript runtime, not the HTML parser.
So, value="6\"
doesn't contain a literal quote. It contains 6\
. The quote after the \
is the closing quote for the value
attribute which causes tall"
to remain as invalid HTML that the HTML parser just ignores. When you pull the value of the input, you would only get 6\
.
You stated that the string gets created correctly, but it doesn't. Look closely at the end of what you say you are getting;
<input id="CTRLText1_3" name="Text1" type="radio" value="Rev 6" tall"="">
tall"=""
is invalid HTML.
To do what I think you are after, you should use single quotes for the HTML attribute and then the double quote can be properly stored for JavaScript to extract later. You won't need any escaping:
console.log(document.querySelector("option").value);
<option value='6" tall'>
Upvotes: 1