How to disable HTML button using JavaScript? - javascript

I’ve read that you can disable (make physically unclickable) an HTML button simply by appending disable to its tag, but not as an attribute, as follows:
<input type="button" name=myButton value="disable" disabled>
Since this setting is not an attribute, how can I add this in dynamically via JavaScript to disable a button that was previously enabled?

Since this setting is not an attribute
It is an attribute.
Some attributes are defined as boolean, which means you can specify their value and leave everything else out. i.e. Instead of disabled="disabled", you include only the bold part. In HTML 4, you should include only the bold part as the full version is marked as a feature with limited support (although that is less true now then when the spec was written).
As of HTML 5, the rules have changed and now you include only the name and not the value. This makes no practical difference because the name and the value are the same.
The DOM property is also called disabled and is a boolean that takes true or false.
foo.disabled = true;
In theory you can also foo.setAttribute('disabled', 'disabled'); and foo.removeAttribute("disabled"), but I wouldn't trust this with older versions of Internet Explorer (which are notoriously buggy when it comes to setAttribute).

to disable
document.getElementById("btnPlaceOrder").disabled = true;
to enable
document.getElementById("btnPlaceOrder").disabled = false;

It is an attribute, but a boolean one (so it doesn't need a name, just a value -- I know, it's weird). You can set the property equivalent in Javascript:
document.getElementsByName("myButton")[0].disabled = true;

Try the following:
document.getElementById("id").setAttribute("disabled", "disabled");

The official way to set the disabled attribute on an HTMLInputElement is this:
var input = document.querySelector('[name="myButton"]');
// Without querySelector API
// var input = document.getElementsByName('myButton').item(0);
// disable
input.setAttribute('disabled', true);
// enable
input.removeAttribute('disabled');
While #kaushar's answer is sufficient for enabling and disabling an HTMLInputElement, and is probably preferable for cross-browser compatibility due to IE's historically buggy setAttribute, it only works because Element properties shadow Element attributes. If a property is set, then the DOM uses the value of the property by default rather than the value of the equivalent attribute.
There is a very important difference between properties and attributes. An example of a true HTMLInputElement property is input.value, and below demonstrates how shadowing works:
var input = document.querySelector('#test');
// the attribute works as expected
console.log('old attribute:', input.getAttribute('value'));
// the property is equal to the attribute when the property is not explicitly set
console.log('old property:', input.value);
// change the input's value property
input.value = "My New Value";
// the attribute remains there because it still exists in the DOM markup
console.log('new attribute:', input.getAttribute('value'));
// but the property is equal to the set value due to the shadowing effect
console.log('new property:', input.value);
<input id="test" type="text" value="Hello World" />
That is what it means to say that properties shadow attributes. This concept also applies to inherited properties on the prototype chain:
function Parent() {
this.property = 'ParentInstance';
}
Parent.prototype.property = 'ParentPrototype';
// ES5 inheritance
Child.prototype = Object.create(Parent.prototype);
Child.prototype.constructor = Child;
function Child() {
// ES5 super()
Parent.call(this);
this.property = 'ChildInstance';
}
Child.prototype.property = 'ChildPrototype';
logChain('new Parent()');
log('-------------------------------');
logChain('Object.create(Parent.prototype)');
log('-----------');
logChain('new Child()');
log('------------------------------');
logChain('Object.create(Child.prototype)');
// below is for demonstration purposes
// don't ever actually use document.write(), eval(), or access __proto__
function log(value) {
document.write(`<pre>${value}</pre>`);
}
function logChain(code) {
log(code);
var object = eval(code);
do {
log(`${object.constructor.name} ${object instanceof object.constructor ? 'instance' : 'prototype'} property: ${JSON.stringify(object.property)}`);
object = object.__proto__;
} while (object !== null);
}
I hope this clarifies any confusion about the difference between properties and attributes.

It's still an attribute. Setting it to:
<input type="button" name=myButton value="disable" disabled="disabled">
... is valid.

If you have the button object, called b: b.disabled=false;

I think the best way could be:
$("#ctl00_ContentPlaceHolder1_btnPlaceOrder").attr('disabled', true);
It works fine cross-browser.

<button disabled=true>text here</button>
You can still use an attribute. Just use the 'disabled' attribute instead of 'value'.

Related

In JavaScript: Why doesn't setting a standard attribute's DOM property to an empty string remove the attribute like Element.removeAttribute() does?

I've learned that it's generally best to use DOM properties to set, access, and modify attributes which has lead me to avoid using setAttribute() and getAttribute(). Is there a similar way to remove DOM attribute properties without using removeAttribute()?
Given this HTML code:
<div id=el></div>
And this JavaScript code:
let el = document.getElementById('el');
console.log(el.outerHTML); //<div id='el'></div>
console.log(el.align === ''); //true
el.align = 'center';
console.log(el.outerHTML); //<div id="el" align="center"></div>
el.align = '';
log(el.outerHTML); //<div id="el" align=""></div>
It appears that el.align is set to an empty string by default. Why does resetting el.align to an empty string after assigning a value to el.align not remove the align attribute from the el.outerHTML presentation? Is this method just as effective even so? Or will this cause issues that removeAttribute() won't?
You need to understand the difference between markup attributes and DOM properties. Attributes don't always directly align with with a property on the JavaScript object.
The mapping between IDL attribute (properties) and the corresponding content attribute (markup) depends on the definition of this Interface Definition Language.
Setting some IDL attributes to false or null will remove them, for instance the ones mapping to boolean attributes, whose simple presence signifies a truthy value:
console.log(aud.loop);
console.log(aud.outerHTML);
aud.loop = false;
console.log(aud.outerHTML);
<audio id='aud' loop></audio>
However, some others like keywords attributes won't get removed, because the value you did set even if not part of the list of valid keywords will map to an invalid default value, for instance HTMLInputElement's type IDL will default to "text", if you set an invalid value, but the markup will still show this invalid value. (Your align attribute was part of this category, before it's been deprecated).
console.log(inp.type); // "number"
inp.type = "foobar"; // invalid
console.log(inp.type); // => default to "text
console.log(inp.outerHTML); // markup: "foobar"
inp.type = null; // invalid
console.log(inp.type); // => default to "text
console.log(inp.outerHTML); // markup: "null"
<input id="inp" type="number">
This makes sense since even though the browser doesn't recognize the set value as being one they support, it could very well be one that will be supported in the future.
The only way to remove such attributes is then to use Element.removeAttribute() method.
Same goes for other attributes which will accept any string as a valid value, for instance class (that is for HTML, CSS have stricter rules), here setting the IDL to any value will coerce it to a string, which will map to a valid in value in the IDL className.
console.log(el.className); // ""
el.className = null; // coerced to string
console.log(el.className); // "null"
console.log(el.outerHTML); // markup: "null"
el.className = false; // coerced to string
console.log(el.className); // "false"
console.log(el.outerHTML); // markup: "false"
el.className = ""; // ""
console.log(el.className); // ""
console.log(el.outerHTML); // markup: ""
<div id="el"></div>
And some will have different default values whether the attribute is missing, or in an invalid state, making their relation with the IDL even more obscure.
// crossOrigin IDL when no set is `null`.
console.log(img.crossOrigin);// attribute unset => IDL `null`
img.crossOrigin = 'use-credentials' // only non default valid value.
console.log(img.crossOrigin);
console.log(img.outerHTML);
img.crossOrigin = false; // invalid
console.log(img.crossOrigin); // IDL defaults to "anonymous"
console.log(img.outerHTML); // markup is `"false"`
img.crossOrigin = null; // remove
console.log(img.crossOrigin);
console.log(img.outerHTML);
<img id="img">
Finally some won't get reflected at all in the content attribute, like the HTMLInputElement.value.
inp.value = "new value";
console.log(inp.outerHTML);
<input id="inp" value="initialValue">
So you'd need to search for the definition of any IDL attribute to be sure how it should behave.

difference between JS get element's attribute with elem.getAttribute(attr) and elem[attr]

I have a problem to get DOM element's attributes in JS. Here is code:
return elem.getAttribute(attr) || elem[attr] || "";
elem.getAttribute(attr) is used to get attributes like name or id, elem[attr] is used to get attribute like tagName. It works fine, until style came out.
In my case, I want to have "" when style attribute not set. But with above code, it will try elem[attr] when elem.getAttribute(attr) returns null. So if style is not set, I get all browser supported styles instead of "".
How to deal with this problem? Is there any better way than enum attributes?
Edit:
I want to write a general function to get element's attributes (such as name, style) or properties(such as tagName).
The main difference is elem.getAttribute(attr) try to get an attribute in the tag element, but elem[attr] try to get a property from an object, is important to know that elem inherits all properties from the Element Object, this properties are declared and in some cases defined, one of this properties is style.
In the particular case of the style property, by default this has been defined with an CSSStyleDeclaration, that's the reason you get attributes of style.
If you want only check if the attribute is in the tag, I suggest you only use this code:
return elem.getAttribute(attr) || "";
This is a code I use on my applications, so I'll just copy & paste it:
Object.defineProperty( Element.prototype, "hashAttr", { get: function(){
/* Bekim Bacaj 2008 */
var hash=[], i = 0, x = this.attributes;
while( x[i] ){hash[x[i].name] = x[i++].value};
return hash;
}})
;
which is, to my knowledge, the fastest possible.
This is a sample return from an element that has no inline or JavaScript assigned styles on its tag.:
>> media.hashAttr
{
width : "100%",
height : "100%",
id : "media",
src : "http://*****.***/stream/*****.mp4",
autoplay : "false",
poster : "http://******.***/thumb/*****.jpg",
type : "video/mp4"
}
Notice that, therefore, no offline style-attribute is present in the property list.
I have an answer. It handles tagName specially. It's not great. But it can get the job done.
var value = elem.getAttribute(attr);
if (!value) {
if (attr == "tagName") {
value = elem["tagName"] || "";
} else {
value = "";
}
}
return value;

jQuery access the default value of a text area

If I have a text input and have set a default value in the HTML, is there anyway to access the original value after jquery has changed the current value using .val()?
It was my understanding that jQuery should be changing the value property and not the value attribute?
Edit: Note I'm not asking how I could store the default value to retrieve it later (e.g. in data or in a var) I'm interested in why jQuery is modifying the attribute of the input field (and in turn the defaultValue) and not just the property.
For this example:
<input id="me" type="hidden" value="starting value" />
<script>
var $field = $('#me');
console.log($field.val());
console.log($field.prop('defaultValue'));
console.log($field.val('new value'));
console.log($field.val());
console.log($field.prop('defaultValue'));
console.log($field.attr('value'));
console.log($field.prop('value'));
</script>
We see:
starting value
starting value
[input#me, context: document, selector: "#me", jquery: "2.1.0", constructor: function, toArray: function…]
new value
new value
new value
new value
Fiddle:
http://jsfiddle.net/jLsqmxg7/1/
jQuery "val" setter always change both the attribute and the property. They do this to not confuse the developer with a ambiguous behavior. If you really want to change only the property and let the tag attribute with the same value do this:
var $input = $("<input>", {value: 'original'}); // Using the jQuery constructor to create a input :)
$input[0].value = "foo"; // Changing the value property of this HTMLInputElement instance
console.log($input.val()); // foo
console.log($input.prop('value')); // foo
console.log($input.attr('value')); // original
With this, you're changing only the HTMLInputElement value property, not the tag attribute.
So, was I say, this turns the code a little confunsing.

Accessing attributes and properties in jquery/javascript

I have a existing application which uses javascript and properties like notNull, isDate etc defined within the elements in html elements like input, select, etc
For example:
<input type = 'text' notNull class='mandatoryField' name = 'abc' id='abc' isDate/>
And the javascript checks for the properties with a hasProp method, placing the code below and corresponding warning messages are displayed:
function hasProp(thisField, thisProp) {
for ( var prop in thisField) {
if (prop == thisProp)
return true;
}
return false;
}
My issue here is with using different browsers - IE, Chrome and Firefox
This particular methods are all ok for Internet Explorer. when it comes to chrome and firefox, the notNull, isDate are treated as attributes rather than properties and the above hasProp method always returns false.
I did go through many questions available here, but couldn't find any way to access both properties and attributes in a single way - I would prefer jQuery to be used, since we will be migrating to jQuery eventually.
Any pointers to this will be really helpful.
Thanks,
Reema
I think the way you use the attribute and property aren't 100% accurate, properties (.prop()) in the jQuery context are basically the value of the attribute in memory, where as .attr() reflects the value in the markup. This is only the case for HTML attributes that are "built-in".
So in your example, you're dealing with attributes all the way, just some don't happen to have any value.
The best way of detecting the presence of an attribute, cross browser using jQuery:
$('#myElement').is('[attrName]') === true
So, in your case:
$('#abc').is('[isDate]') === true
See this JS-Fiddle
As you want a jQuery solution, you can use both jQuery.attr() and jQuery.prop() methods to solve your problem.
I would prefer an pure Javascript approach:
var attributes = ['notNull', 'isDate'],
checkForAttribute = function(elem){
for(var i = 0, c = attributes.length ; i < c ; i++){
if(elem.getAttribute(attributes[i]) !== null){
console.log("attribute " + attributes[i] + " found");
}else{
console.log("attribute " + attributes[i] + " not found");
}
}
}
See an working example here.
Here is some more information on the getAttribute() method.

Prototype's weird supported environment check

I was looking at the PrototypeJS code and found this check -
var div = document.createElement('div'),
form = document.createElement('form'),
isSupported = false;
if (div['__proto__'] && (div['__proto__'] !== form['__proto__'])) {
isSupported = true;
}
I would like to know what are the cases where this condition returns false -
div['__proto__'] !== form['__proto__']
Note: The function's comment says - "Used internally to detect if the browser supports extending html element prototypes". Not sure how this check helps for that.
This test allows PrototypeJS to figure out if it can add specific methods to specific types of element prototypes.
For example you would not want the method getInputs() (which returns an array of all of the form's elements) on a <div> element because it would only make sense being used on a <form> element.
HTML
<div id='mydiv'></div>
<form id='myform'></form>
JS
$('mydiv').addClassName('newclass'); //does not error
$('myform').addClassName('newclass'); //does not error
$('myform').getInputs(); //does not error
$('mydiv').getInputs(); //throws error 'has no method getInputs()'
Example on JSFiddle http://jsfiddle.net/C39gu/

Categories