how to build a valid url inside my javascript - javascript

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.

Related

How to get the number of input tags containing certain text?

My goal is to flag when a user enters the same text into one input that matches at least one other input's text. To select all of the relevant inputs, I have this selector:
$('input:text[name="employerId"]')
but how do I select only those whose text = abc, for instance?
Here is my change() event that checks for duplicate text among all the inputs on the page. I guess I am looking for something like :contains but for text within an input.
var inputsToMonitorSelector = "input[type='text'][name='employerId']";
$(inputsToMonitorSelector).change(function() {
//console.log($(this).val());
var inputsToExamineSelector = inputsToMonitorSelector
+ ":contains('" + $(this).val() + "')";
console.log(inputsToExamineSelector);
if($(inputsToExamineSelector).length > 1) {
alert('dupe!');
}
});
Or is there no such selector? Must I somehow select all the inputsToMonitorSelector's and, in a function, examining each one's text, incrementing some local variable until it is greater than one?
With input you need to use [value="abc"] or .filter()
$(document).ready(function() {
var textInputSelector = 'input[type="text"][name="employerId"]';
$(textInputSelector).on('input', function() {
$(textInputSelector).css('background-color', '#fff');
var input = $(this).val();
var inputsWithInputValue = $(textInputSelector).filter(function() {
return this.value && input && this.value == input;
});
var foundDupe = $(inputsWithInputValue).length > 1;
if(foundDupe) {
console.log("Dupe found: " + input);
$(inputsWithInputValue).css('background-color', '#FFD4AA');
}
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<input type="text" name="employerId" value="abc">
<input type="text" name="employerId" value="">
<input type="text" name="employerId" value="">
<input type="text" name="employerId" value="">
[value="abc"] means if the value is abc
[value*="abc"] * means if the value contains abc
[value^="abc"] ^ means if the value starts with abc
[value$="abc"] $ means if the value ends with abc
Note: :contains() not for inputs , and word text not used with inputs and <select>.. inputs and <select> has a value
In your case .. instead of using
$(inputsToExamineSelector).length > 1)
You may need to use .filter()
$(inputsToExamineSelector).filter('[value*="abc"]').length > 1)
OR
$('input[type="text"][name="employerId"]').filter(function(){
return this.value.indexOf('abc') > -1
// for exact value use >> return this.value == 'abc'
}).length;
And to use a variable on it you can use it like
'[value*="'+ valueHere +'"]'
Something like this works. Attach isDuplicated(myInputs,this.value) to a keyup event listener attached to each input.
var myInputs = document.querySelectorAll("input[type='text']");
function isDuplicated(elements,str){
for (var i = 0; i < myInputs.length; i++) {
if(myInputs[i].value === str){
myInputs[i].setCustomValidity('Duplicate'); //set flag on input
} else {
myInputs[i].setCustomValidity(''); //remove flag
}
}
}
Here's another one. I started with vanilla js and was going for an answer like Ron Royston with document.querySelector(x) but ended up with jquery. A first attempt at several things but here you go:
$("input[type='text']").each(function(){
// add a change event to each text-element.
$(this).change(function() {
// on change, get the current value.
var currVal = $(this).val();
// loop all text-element-siblings and compare values.
$(this).siblings("input[type='text']").each(function() {
if( currVal.localeCompare( $(this).val() ) == 0 ) {
console.log("Match!");
}
else {
console.log("No match.");
}
});
});
});
https://jsfiddle.net/xxx8we6s/

Prettify JSON object alert

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"));

Encoding and Decoding JSON in Hidden HTML element

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

convert span id text into link and display as text

The scenario is: User choose a entry from dropDown list. Referring to the relevant entry i will create a new prefix for the webpath existing in . But the problem I have, the will not interpret as a link part, so the link won't be generated!
Use Case: If User choose link1 from dropDown-list, the result should be:https://link1//web/sso/bw/ostrfer.jsp (as link and as text display)
Could you help me how I can reach this?
Many thanks for your help! :)
JS:
function output (choice) {
var index = choice.selectedIndex;
var prefix = "";
if(index == 1)
prefix = "https://link1";
else if (index == 2)
prefix = "https://link2;
else if (index == 3)
prefix = "https://link3";
else if (index == 4)
prefix = "https://link4";
else if (index == 5)
prefix = ""https://link5";
document.getElementById("url").innerHTML = praefix;
}
HTML:
<body>
<form>
<p>
<select id = "list" name = "list" onchange ='output(this.form.liste);' >
<option></option>
<option>link1</option>
<option>link2</option>
<option>link3</option>
<option>link4</option>
<option>link5</option>
</select>
</p>
</form>
</span>/web/sso/bw/ostrfer.jsp> <span id = "url"></span> /web/sso/bw/ostrfer.jsp
</body>
See this demo:
http://jsfiddle.net/JFqrH/3/
HTML:
<form>
<p>
<select id = "list" name = "list" onchange ='output(this);' >
<option></option>
<option>link1</option>
<option>link2</option>
<option>link3</option>
<option>link4</option>
<option>link5</option>
</select>
</p>
<a id="url" href="/web/sso/bw/ostrfer.jsp">/web/sso/bw/ostrfer.jsp</a>
<a id="url1" href="/web/sso/bw/ostrfer.jsp">/web/sso/bw/ostrfer1.jsp</a>
<a id="url2" href="/web/sso/bw/ostrfer.jsp">/web/sso/bw/ostrfer2.jsp</a>
</form>​
JS:
function output (choice) {
var index = choice.selectedIndex;
var prefix = "";
if(index == 1)
prefix = "https://link1";
else if (index == 2)
prefix = "https://link2";
else if (index == 3)
prefix = "https://link3";
else if (index == 4)
prefix = "https://link4";
else if (index == 5)
prefix = "https://link5";
updateLink(document.getElementById("url"), prefix);
updateLink(document.getElementById("url1"), prefix);
updateLink(document.getElementById("url2"), prefix);
}​
function updateLink(url, prefix) {
if(!url.getAttribute("postfix")) {// need to save orignal href as it will be replaced later
url.setAttribute("postfix", url.getAttribute("href"));
}
var postfix = url.getAttribute("postfix");
url.innerHTML = prefix + postfix;
url.href = prefix + postfix;
}
You have multiple syntax errors in your code. Plus a href=<span id = "url"></span> is nonsence. It can't work. Instead of that you should use attributes (see getAttribute/setAttribute). Also, it is much simpler to use swithc statement instead of if/else. Another thing: onchange=output(this.form.liste); - instead of this you can use onchange=output(this); as this will already point to your dropdown element there.
The question is pretty unclear, does this work?
document.getElementById("url").innerHTML = prefix + document.getElementById("url").innerHTML;
You could store the this snippet:
/web/sso/bw/ostrfer.jsp
as a constant like so:
var uri = "/web/sso/bw/ostrfer.jsp";
Then when the user selects the link you could append it like so:
var elem = document.getElementById("url");
elem.setAttribute('href', prefix + uri);
This should update the "href" attribute of the anchor tag with the new url.
I setup a test example so you can see it in action in this Fiddle. If you inspect the link with the browsers developer tools you can see that the href (originally an empty string "") has now been updated after executing the code to be "https://link1/web/sso/bw/ostrfer.jsp".
Hope this helps.
You have multiple syntax errors that are causing the problem:
First
prefix = "https://link2;
^ missing close quote here
Second
prefix = ""https://link5";
^ remove the extra quote here
Third
document.getElementById("url").innerHTML = praefix;
^ should be prefix
Fourth
<select id = "list" name = "list" onchange ='output(this.form.liste);' >
^ should be list or just 'this'
Even with the syntax errors, your code is still not right - it's not good to have a <span> within the href of an <a>.
Try this jsFiddle Demo - I changed the way the code works, it doesn't use the span.
Full fixed code:
<script>
function output () {
var index = this.selectedIndex;
var prefix = "";
var suffix = "/web/sso/bw/ostrfer.jsp";
prefix = "https://" + this.value;
var link = document.getElementById("url");
link.href = prefix + suffix;
link.innerHTML = prefix + suffix;
}
window.onload = function()
{
document.getElementById("list").onchange = output;
}​
</script>
<form>
<p>
<select id = "list" name = "list" >
<option></option>
<option>link1</option>
<option>link2</option>
<option>link3</option>
<option>link4</option>
<option>link5</option>
</select>
</p>
</form>

How can I disable an <option> in a <select> based on its value in JavaScript?

I have a <select> with a number of <option>s. Each has a unique value. I need to disable an <option> with a given defined value (not innerHTML).
Anyone have an idea how?
JavaScript, in 2022
You can use querySelectorAll, and forEach off of the resulting NodeList to do this same thing more easily in 2022.
document.querySelectorAll("#foo option").forEach(opt => {
if (opt.value == "StackOverflow") {
opt.disabled = true;
}
});
Do be mindful of string-comparisons, however. 'StackOverflow' and 'stackoverflow' are not the same string. As such, you can call .toLowerCase() on strings before comparing, or even go with a case-insensitive regular expression comparison like the this:
if ( /^stackoverflow$/i.test(option.value) ) {
option.disabled = true;
}
Pure Javascript (2010)
With pure Javascript, you'd have to cycle through each option, and check the value of it individually.
// Get all options within <select id='foo'>...</select>
var op = document.getElementById("foo").getElementsByTagName("option");
for (var i = 0; i < op.length; i++) {
// lowercase comparison for case-insensitivity
(op[i].value.toLowerCase() == "stackoverflow")
? op[i].disabled = true
: op[i].disabled = false ;
}
Without enabling non-targeted elements:
// Get all options within <select id='foo'>...</select>
var op = document.getElementById("foo").getElementsByTagName("option");
for (var i = 0; i < op.length; i++) {
// lowercase comparison for case-insensitivity
if (op[i].value.toLowerCase() == "stackoverflow") {
op[i].disabled = true;
}
}
###jQuery
With jQuery you can do this with a single line:
$("option[value='stackoverflow']")
.attr("disabled", "disabled")
.siblings().removeAttr("disabled");
Without enabling non-targeted elements:
$("option[value='stackoverflow']").attr("disabled", "disabled");
​
Note that this is not case insensitive. "StackOverflow" will not equal "stackoverflow". To get a case-insensitive match, you'd have to cycle through each, converting the value to a lower case, and then check against that:
$("option").each(function(){
if ($(this).val().toLowerCase() == "stackoverflow") {
$(this).attr("disabled", "disabled").siblings().removeAttr("disabled");
}
});
Without enabling non-targeted elements:
$("option").each(function(){
if ($(this).val().toLowerCase() == "stackoverflow") {
$(this).attr("disabled", "disabled");
}
});
Set an id to the option then use getElementById and disable it when x value has been selected, like so:
<body>
<select class="pull-right text-muted small"
name="driveCapacity" id=driveCapacity onchange="checkRPM()">
<option value="4000.0" id="4000">4TB</option>
<option value="900.0" id="900">900GB</option>
<option value="300.0" id ="300">300GB</option>
</select>
</body>
<script>
var perfType = document.getElementById("driveRPM").value;
if(perfType == "7200"){
document.getElementById("driveCapacity").value = "4000.0";
document.getElementById("4000").disabled = false;
}else{
document.getElementById("4000").disabled = true;
}
</script>
For some reason other answers are unnecessarily complex, it's easy to do it in one line in pure JavaScript:
Array.prototype.find.call(selectElement.options, o => o.value === optionValue).disabled = true;
or
selectElement.querySelector('option[value="'+optionValue.replace(/["\\]/g, '\\$&')+'"]').disabled = true;
The performance depends on the number of the options (the more the options, the slower the first one) and whether you can omit the escaping (the replace call) from the second one. Also the first one uses Array.find and arrow functions that are not available in IE11.
Use a straightforward selector:
document.querySelector('select[name="theName"] option[value="theValue"]').disabled = true;
Here with JQuery, if anybody search it:
var vals = new Array( 2, 3, 5, 8 );
select_disable_options('add_reklamaciq_reason',vals);
select_disable_options('add_reklamaciq_reason');
function select_disable_options(selectid,vals){
var selected = false ;
$('#'+selectid+' option').removeAttr('selected');
$('#'+selectid+' option').each(function(i,elem){
var elid = parseInt($(elem).attr('value'));
if(vals){
if(vals.indexOf(elid) != -1){
$(elem).removeAttr('disabled');
if(selected == false){
$(elem).attr('selected','selected');
selected = true ;
}
}else{
$(elem).attr('disabled','disabled');
}
}else{
$(elem).removeAttr('disabled');
}
});
}
I would like to give you also the idea to disable an <option> with a given defined value (not innerhtml). I recommend to it with jQuery to get the simplest way. See my sample below.
HTML
Status:
<div id="option">
<select class="status">
<option value="hand" selected>Hand</option>
<option value="simple">Typed</option>
<option value="printed">Printed</option>
</select>
</div>
Javascript
The idea here is how to disable Printed option when current Status is Hand
var status = $('#option').find('.status');//to get current the selected value
var op = status.find('option');//to get the elements for disable attribute
(status.val() == 'hand')? op[2].disabled = true: op[2].disabled = false;
You may see how it works here:
https://jsfiddle.net/chetabahana/f7ejxhnk/28/
You can also use this function,
function optionDisable(selectId, optionIndices)
{
for (var idxCount=0; idxCount<optionIndices.length;idxCount++)
{
document.getElementById(selectId).children[optionIndices[idxCount]].disabled="disabled";
document.getElementById(selectId).children[optionIndices[idxCount]].style.backgroundColor = '#ccc';
document.getElementById(selectId).children[optionIndices[idxCount]].style.color = '#f00';
}
}

Categories