Can't set disabled=false (javascript) - javascript

I have this function:
function disableDiv(divId, action){
var divId = byId(divId);
if(action==true){
divId.style.display='none';
}
else if(action==false){
divId.style.display='block';
}
var inputs = divId.getElementsByTagName("input");
var selects = divId.getElementsByTagName("select");
var i;
for (i=0; i<inputs.length; i++){
inputs[i].disabled=action;
}
for (i=0; i<selects.length; i++){
selects[i].disabled=action;
}
}
This takes a divId (id of DIV) and an action (false or true) and gets all inputs and selects inside the div, and sets their disabled attribute to either false or true.
According to Firebug, the elements inside the Div are disabled all the time. But they should be active once hitting a drop-list option... The triggering is fine so you know.
I can see this function beeing called by using alert boxes, and it does in fact set the disabled=false. But the elements are still disabled.
Something to point out is that according to firebug, the disabled attribute looks like this:
<input name="test" id="test" disabled="">
Note there is just two doublequotes... Shouldn't it say "disabled='disabled'" or "disabled=true"?
Any tips on how to troubleshoot further?
Here is how I call the function:
(category=="Cars")?disableDiv("nav_sub_cars", false):disableDiv("nav_sub_cars", true);
If you need more input, just let me know...
Thanks

Edited to reflect the comments.
According to the W3C the code you posted should be correct. The disabled attribute is a boolean attribute. Use of the removeAttribute() method may be helpful as well.
In my experience, you can also achieve this effect using the string values 'disabled' or ''. This may work because these values are coerced into a boolean representation when the browser encounters them.

try .disabled = null or .removeAttribute('disabled'). My understanding is that it's the presence or absence of the disabled attribute that governs disabledness, not its value.

To disable elements you need to use attribute disabled = "disabled" rather than true or false. To make it enabled again, you need to remove the disabled attribute. Modify your code like this:
for (i=0; i<inputs.length; i++){
if (action === false) {
inputs[i].removeAttribute('disabled');
}
else {
inputs[i].setAttribute('disabled', 'disabled');
}
}
for (i=0; i<selects.length; i++){
if (action === false) {
selects[i].removeAttribute('disabled');
}
else {
selects[i].setAttribute('disabled', 'disabled');
}
}
The setAttribute and removeAttribute functions are used to set and remove disabled attribute respectively.

More code needed. Everything looks correct, and setting the disabled property of an <input> element to a Boolean value (the correct approach) certainly works in Firefox, regardless of the presence or absence of the disabled attribute in the source HTML.

Related

Error if targeting multiple element Id's with Javascript and one of then is not found

I am trying to target multiple IDs with JavaScript so that I can disable the input field for them. It seems to be pretty straight forward using the following script, but I noticed that on pages where the middle Element does not exist, the script does not disable the 3rd one (as though it just stops working when not finding the second element).
<script>
document.getElementById("id_1").disabled = true;
document.getElementById("id_2").disabled = true;
document.getElementById("id_3").disabled = true;
</script>
So on pages when all 3 IDs exist, the script works perfectly. But on pages where either "id_1" or "id_2" does not exist, the remaining elements are not disabled even if they do exist.
Is there any way around that? Note that I can not create separate scripts for each page because this will go in the footer which is the same for all pages.
Thanks!
You should test for the existence first, then disable it if it exists. I also put the id's in an array to simplify the code.
var ids = ['id_1','id_2','id_3'];
for (var i = 0; i < ids.length; i++) {
var el = document.getElementById(ids[i]);
el && (el.disabled = true);
}
<input id="id_1" value="id_1">
<input id="id_3" value="id_3">
This is because document.getElementById returns null when the element has not been found, so effectively you're causing an exception while trying to set disabled on null. This would be the case when one of the elements are not set in the DOM. What you will have to do is check whether the element has been found correctly then set the element or loop through them all.
TL;DR:
The reason that the script stops working is that it is throwing an error when you try to disable an element that doesn't exist.
In Detail:
document.getElementById() will return null if the element that you tried to find does not exist (Here's the MDN page).
When you try to set the .disabled property to true on null JavaScript will throw a TypeError. Unless you handle that error with a try/catch block it will cause your script to stop executing and the later input elements will not become disabled.
Solution
To fix this you'll want to check that your element actually is an element before trying to set it to disabled. Something like this:
var el = document.getElementById('id_1');
if ('null' !== typeof el) {
el.disabled = true;
}

onkeyup, get value from textbox, update another textbox, not working

Here is the javascript:
function changeText(containerId) {
var datatext = document.getElementById('masterText').value;
var collection = document.getElementById(containerId).getElementsByTagName('INPUT');
for (var x = 0; x < collection.length; x++) {
if (collection[x].type.toUpperCase() == 'TEXTBOX')
collection[x].value = datatext;
}
}
and this is the html
<input id="masterText" type="textbox" onkeyup="changeText('divGrid')"><br />
<div id="divGrid">
<input type="textbox"><br />
<input type="textbox"><br />
<input type="textbox"><br />
<input type="textbox"><br />
</div>
Suppose that all the textbox's value will change, but it is not. Do you know what is the error?
As I said in the comments, textbox is not a valid type for <input> elements. Although unknown types default to text, it might have somehow messed up the js (maybe the type property doesn't work right with unknown types), and changing it to just text seems to work fine, as you can see in this jsbin: http://jsbin.com/xakoxeyi/1/
My best guess at why this is happening is that using element.type doesn't work right with unknown types, so it doesn't have the value textbox, even though that's what html says. The best way to fix this is to change everything to text instead (as I said above), but another great way is to, instead of using collection[x].type, to use collection[x].getAttribute('type'), as using getAttribute always gives you what's in the HTML attribute
Just to expand on what Markasoftware said:
Had you chosen to get the attribute type, using getAttribute, your code would have worked.
function changeText(containerId) {
var datatext = document.getElementById('masterText').value;
var collection = document.getElementById(containerId).getElementsByTagName('INPUT');
for (var x = 0; x < collection.length; x++) {
if (collection[x].getAttribute('type').toUpperCase() == 'TEXTBOX') {
collection[x].value = datatext;
}
}
}
JSFiddle: http://jsfiddle.net/MSTUe/
So, my guess is that behind the scenes, an unknown type gets set as a text input, however you can still query an input with textbox, if needed. Probably for those awesomely new (but poorly supported) HTML5 inputs (like color, datetime-local, week, etc.) that a browser may not support.

Identify Hidden Form Value Without an ID or Class

I am writing a Greasemonkey script and I need to be able to take the value from a hidden form element and set it to a variable.
The hidden form value looks like this:
<input type="hidden" name="ASIN" value="B009MO89Y4" />
I have no ID, class, or any way I can see to set the "value" to a variable. This needs to work dynamically and I currently have no way to establish a class or ID to this value.
Is there a Javascript (or jQuery) method to set this?
In other words:
Find "input" with name "ASIN" and set .val() to a variable?
This selector and assignment:
$("input[name='ASIN']").val(); <---- returns value of that input
var inputVal = $("input[name='ASIN']").val(); <-- Assigns it
var temp = "Stuff";
$("input[name='ASIN']").val(temp); <----Assigns the value of the temp var.
You can use the jQuery attribute equals selector
$('input[name="ASIN"]').val(foo);
You can select it via. name in jQuery like so:
var bar = "Example"; // Example text, to be used in val().
var x = $('input[name="ASIN"]').val(bar);
// Sets the variable x to be the value bar for the input with the name ASIN.
Here's a working jQuery jsFiddle.
In pure Javascript *:
var bar = "Example";
document.getElementsByName("ASIN")[0].value = bar;
Here's a working Javascript jsFiddle.
*Please note that although document.getElementsByName is supported well in Firefox, Chrome and Safari, it has limited browser support. in IE and Opera.
Like this:
$('input[name="ASIN"]').val();
Var:
var hiddenAsin = $('input[name="ASIN"]').val();
You can filter your selection with any attribute.
$('input[name=ASIN]').val("New Value")
You can use selector that targets inputs of type hidden. It should look like that:
$('input[type=hidden]');
or simpler:
$(':hidden');
Use this method
var inputs = document.getElementsByTagName('input');
for(var i = 0...)
{
//go through each input and look for the name "ANSI" and the type is hidden.
//and do your changes.
}
this is for javascript remember.
with this you should be able to get that specific hidden form without an ID nor a Class assigned to that specific form.
For pure javascript:
Try document.getElementsByName('name').
Note that cmptrgeekken pointed out that this has limited browser-support (although that would not be an issue with greasemonkey in FF).
As an alternative, if that hidden element has a fixed place you could also access it by index-number in a predictable collection that you got from knownParent.getElementsByTagName('tag')[#] (So the first hidden inputtag inside a form would be number 0).
Another variation is to get (again) knownParent.getElementsByTagName('tag') and loop over that collection to see what element has the 'name' attribute set that you seek.
Simply do:
var target=knownParent.getElementsByTagName('input'), L=target.length;
while(L--){ if(target[L].name==='name'){target=target[L]; break;} }
alert(target.value); //target is now the element you seek.
Example fiddle here.
Good luck!

jQuery setting input.value = input.title (or other input attribute)

I'm trying to figure out how to set the input value of a text field to the value of it's title when the page loads, as a way to show placeholder text. I'm using an HTML4 Strict doctype. I don't want to store the placeholder text in the input value, because I don't want people without javascript to have to delete the text before typing. I want it to be added with javascript, and then removed when the input gains focus. I have the focus() and blur() methods working, but I can't figure out how to write the initial pageload function to pass the input's title to the val() function.
I currently have this code:
// This doesn't work, it grabs the page title:
$('#item-search').val(this.title);
// Works:
$('#item-search').focus(function() {
if (this.value == this.title) {
this.value = '';
}
});
// Works:
$('#item-search').blur(function() {
if (this.value == '') {
this.value = this.title;
}
});
Just to add another variation, .val() can accept a function as its parameter, fixing your this issues:
$('#item-search').val(function () {
return this.title;
});
this refers to the current scope. In your first example, its referring to document.
You may want.
$('#item-search').val($('#item-search').attr('title'));
Even better:
var $itemSearch = $('#item-search');
$itemSearch.val($itemSearch.attr('title'));
$('#item-search').val(this.title);
In this line this refer the document(html) and set the <title>. To accomplish you job do this:
$('#item-search').val($('#item-search').attr('title'));
Try this:
$('#item-search').val($('#item-search').attr('title'));
Please try this.
$('#item-search').val($("#item-search").attr("title"));

How to get form fields from a specific fieldset?

I'm writing a HTML form that's divided in fieldsets, and I need to get the form fields from a specific fiedset in a function.
Currently it's like this:
function conta(Fieldset){
var Inputs = Fieldset.getElementsByTagName("input");
var Selects = Fieldset.getElementsByTagName("select");
/* Doing the stuff I need to do in two iterations, one for each field type */
}
But who knows what the future may hold, and if the form gets some new field types (radios, checkboxes) this could become awful to mantain.
I know that form elements have the elements attribute that returns all the form fields and I was hoping I could use something like that.
(I know I still gotta discriminate the field type in a bunch of conditionals inside the iteration, but I think it would be faster and easier to keep. Unless it isn't and I should not be doing it)
#Ryan is on the right track if you want to use jQuery (and I would), but I'd suggest something more along the lines of:
$('fieldset#fieldset1 > input[type=text]').each( function() {
... do something for text inputs }
);
$('fieldset#fieldset1 > input[type=radio]').each( function() {
... do something for radios }
);
$('fieldset#fieldset1 > select').each( function() {
... do something for selects }
);
$('fieldset#fieldset1 > textarea').each( function() {
... do something for textareas }
);
As an improvement over if-then-else constructs.
Radio buttons and checkboxes are still input tags and will be in the Inputs var. The problem is, you'll need to add handlers for the checked state to see which radio buttons and checkboxes are selected.
Even worse, you can have more than one radio button and checkbox with the same name... in fact you have to for radio buttons or they don't work as expected.
No jQuery, no problem:
function condat(fieldset) {
var tagNames = ['input', 'select', 'textarea']; // Insert other tag names here
var elements = [];
for (var i in tagNames)
elements.concat(fieldset.getElementsByTagName(tagNames[i]);
for (var i in elements) {
// Do what you want
}
}
Filip Dupanović solution together with the second Cargowire comment worked for me, but only with a minor modification. Cargowire's second comment only produced an array which just holds the sliced characters of the tagNames array (I would have written this in a comment, but I lack the rep so far).
Here is what worked:
function condat(fieldset) {
var tagNames = ['input', 'select', 'textarea']; // Insert other tag names here
var elements = [];
for (var i in tagNames) {
elements = elements.concat([].slice.call(fieldset.getElementsByTagName(tagNames[i])));
}
for (var i in elements) {
// Do what you want.
// Attributes of the selected tag's can be referenced for example as
// elements[i].value = ...;
}
}
A usefull application of this would be to define buttons which only reset a fieldset instead of the whole form. Just use elements[i].value = elements[i].defaultValue; in the //do what you want part, for text inputs to be reseted. And of course bind the condat function onto the onclick event of the button providing the fieldset dom element as a paramenter.
Haven't tested this and don't know how it would work, but you could use JQuery here to select all the elements into a JQuery object
//$("input select textarea").each(function() {
$(":input").each(function() { //even better
// do stuff here
});
this would at least cleanup the code, although you would still have to add conditional statements based on field type like you mentioned.
You should use just querySelectorAll:
function condat(fieldset) {
var elements = fieldset.querySelectorAll('input, select, textarea');
elements.forEach(function(element){
// Do what you want with every element
});
}

Categories