Reputation: 13
I'm not really a programmer, but I have to change some html/css/js code for our needs.. and I'm struggling.
we are using a cloud software, which closed source, but with the possibility to change parts of the HTML frontend.
the software uses the CSS class "dom-admin" to hide some setting for non-admin.
<div class="dom-admin"> hidden for non-admins </div>
if a user logs in, the display property is set by the system to display:none;
.dom-admin {
display: none;
}
these hidden fields are mostly input fields. we dont want to hide this fields for our users, we just want to set the fields readonly
.
my idea is to read the display value within a javascript in a if / else query:
if (dom-admin('display') == 'none')
{ document.write('<input type="text" id="XX">') }
else
{ document.write('<input readonly type="text" id="XX">') }
My Problem is to access the display value, i tried x examples from the net, but i never able to read the property of "dom-admin", eg:
document.getElementById('dom-admin').style.display
Chrome Javascript Console: Uncaught TypeError: Cannot read property 'style' of null
Chrome dev-tools shows me this about the "dom-admin" CSS:
I appreciate any help... Thanks, Patrick
Upvotes: 1
Views: 1518
Reputation: 43870
The class .dom-admin
is merely presentational, it is not a security measure. If you want to access multiple elements with the className of dom-admin
you must collect them into a NodeList/HTMLCollection:
var DOMObjects = document.querySelectorAll('.dom-admin');
OR
var DOMObjects = document.getElementsByClassName('dom-admin');
With this list you'll have to iterate/loop through each *.dom-admin
by a for
loop, or array method (if the latter them the list might need to be converted to an array):
for (let i=0; i < DOMObjects.length; i++) {...
OR
DOMObjects.forEach(function(DOMObj, index) {...
To reverse the style of .dom-admin
, you can set each *.dom-admin
style
object to:
DOMObj.style.display = "block"
OR remove .dom-admin
class:
DOMObj.classList.remove('dom-admin')
The most direct method is to target the className via querySelector()
or getElementsByClassName()[0]
:
var DOMObj = document.querySelector('.dom-admin');
OR
var DOMObj = document.getElementsByClassName('dom-admin')[0];
id
, class
, readOnly
, etc. are called attributes. The attribute needed has a Boolean value (true/false). An attribute such as readonly
merely needs to exist on the tag in order for it to be true. Not actually be in the tag of course makes it false.
Set an attribute More specifically, adding an attribute to an element when it didn't exist before:
DOMObj.setAttribute('readonly', true);
Get an attribute Finding an attribute and reading the value of said attribute:
DOMObj.getAttribute('readonly');
Change an attribute If the attribute already exists and the value needs to be changed:
DOMObj.removeAttribute('readonly')
Keep in mind that the attribute you are dealing with has a Boolean value so it is handled differently than an attribute with a String value.
DOMObj.setAttribute('name', 'foo'); /*OR*/ DOMObj.name = "foo"
DOMObj.getAttribute('name');
DOMObj.setAttribute('name', 'bar') /*OR*/ DOMObj.name = 'bar'
The syntax for methods querySelector()
/querySelectorAll()
:
document.querySelector('.dom-admin')
CSS Selector ===========^-----^[dot for class]
is different than the syntax of method getElementsByClassName()
:
document.getElementsByClassName('dom-admin')
DOMString====================^------^[no dot needed]
document.getElementsByClassName('dom-admin')[0]
DOMString====================^------^===^-^[no dot needed]==
[Bracket Notation with index of zero is needed if there is only one target]
Do not use document.write
unless you intend to destroy everything on your page.
If you have inputs nested within the div.dom-admin
, that would mean that those inputs exist already but the user cannot see them. It isn't necessary to create them and even if you do need to create any element, never use document.write
. Instead use createElement()
or use innerHTML
on an element that you intend to use as a container.
// Collect all .dom-admin into NodeList
var das = document.querySelectorAll('.dom-admin');
// forEach() .dom-admin, remove the class .dom-admin
das.forEach(function(da, idx) {
da.classList.remove('dom-admin');
// Find all inputs in the div formerly known as .dom-admin
var inputs = da.querySelectorAll('input');
/* forEach() input nested within the div formerly known
|| as .dom-admin, set its attribute readonly to true
*/
inputs.forEach(function(input, index) {
input.setAttribute('readonly', true);
});
});
.dom-admin {
display: none;
}
input {
font: inherit;
width: 40%
}
<div class="dom-admin">
<input type='text' value='These inputs exist already'>
<input type='text'>
</div>
<div class="dom-admin">
<input type='text' value='Do not use document.write'>
<input type='text' value='it will overwite EVERYTHING'>
<input type='text' value=''>
</div>
<div class="dom-admin">
<input value='Fun fact:'>
<input value='input by default is type="text"'>
<input>
</div>
Upvotes: 2
Reputation: 2232
Here's what I used to achieve what you want.
As others mentioned, use document.querySelector('.dom-admin')
to access the class and when you change display
style, you can use the if statement
let admin = document.querySelector('.dom-admin');
if (admin.style.display === 'none') {
document.write('<input type="text" id="XX">');
} else {
document.write('<input readonly type="text" id="XX">');
}
.dom-admin {
width: 200px;
display: none;
}
<div class="dom-admin">
<form action="#">
<input type="text" id="user" />
<input type="number" id="user_number" />
<input type="password" id="user_password" />
<input type="submit" id="submit" />
</form>
</div>
Upvotes: 0