In a nutshell I'm trying to target an element within the DOM, then inject a class on the fly to later alter that element.
The situation is as follows, I am working with an application that has predetermined mark up (Manage Engine). It's a tool for system work flows, creating a centralized portal for ticket logging, asset management blah blah. So I use the tool to create templates for end users to log service requests. This is accessed via a web interface portal which in turn obviously has mark up.
So far I have been able to alter specific things such as background colors on table headers for example. I achieve this by creating a rule to fire within that template upon load time. So essentially I am allowing the template to load with its predetermined code and then I am applying a for loop to alter the code once it has loaded. (Hacky I know, however its working really well).
The issue I'm running into now is that certain things within the mark up are generic (no class or id associated to the element). My plan is to target that specific generic element as a variable then add my own class to it upon load. Is there a way to target an element that has a class and then target the child elements within, save that child as a variable to then add a class on the fly with javascript. Please see example below.
<tr class=test1>
<td>
<input>
<input>
<input>
</td>
<tr/>
So with the example above what I am trying to achieve is add my own class with JavaScript to the <td> element. Obviously if i target just <td> it will alter all <td> elements within the markup. Can i get to that specific <td> via the <tr> parent with the test1 class. I am currently unable to use any jquery requests as the base code can not be touched.
Again I know this is a little backwards and hacky but it does work with anything I can specifically target (has a class or id). I need to be able to do this with pure JavaScript. Any suggestions or help is greatly appreciated, apologies if this is a noob approach or question, first time posting in a forum. Let me know if further examples or information is required.
document.querySelector("body").children can get all child elements of body
step1: Select the class. The variable t1 will contain an Array of tr elements.
var t1 = document.querySelector('.test1');
step2: Get the first value from the array t1. So, tr_el1 contains one tr element.
var tr_el1 = t1[0];
step3: Get the children of tr. td_el contains an Array of td elements.
var td_el = tr_el1.children;
Now you can use the td from the td_el array
var tr = document.getElementsByClassName('test1')[0]
var td = tr.children[0]
var inputs = Array.prototype.slice.apply(td.children)
Now you got your inputs inside an array. You're welcome ;-)
Thanks a lot for the assistance, really appreciate it. The examples above helped me build a hybrid that although not exact has given me the outcome i needed.
var parent = document.querySelector(".roweven").children;
var nS;
for (nS = 0; nS < parent.length; nS++) {
parent[nS].style.position = "absolute";
parent[nS].style.width = "100%";
}
I am yet to wrap this up in a function but working as intended. Thanks again :) :)
Related
I am working on a system that creates light box popups in order to deal with user requests appropriately, and for this, elements are built dynamically on the parent window.
When a user clicks a link, it has an onclick action that needs to refer to the parent window in order to get the desired information, but the issue lies in the fact that it does not have an id and it is not an option to add one to the elements themselves.
I have tried many things, including but not exhaustive of:
var obj = window.parent.document.{name};
var obj = jQuery(window.parent.document.{name});
var obj = window.top.document.{name};
The element is a simple hidden input element that is built at time of page load and looks something akin to:
<input type="hidden" name="{name}" value="1|2|3" />
Any ideas on how to achieve this goal are greatly appreciated.
Note: Any use of {name} within this are merely to show where the elements name is and not that it IS that
You can select elements (which have 'special' attribute value) with:
document.querySelector('input[name="{name}"]')
or, with the own selector of the attribute:
document.getElementsByName('{name}')[0]
So this is an interesting one and may very well be impossible to do efficiently. But I'm interested in finding an efficient way to query all html elements in the document that have a particular value set for any attribute. So, for example, instead of this:
document.querySelectorAll('[attrName]');
I'm looking for the equivalent of the following pseudo-code:
document.querySelectorAll('[*=specificValue]');
So essentially the result would be all elements that have any attribute whose value matches "specificValue". I know there are gross ways to do this such as:
var all = document.querySelectorAll('*');
var matches = [];
var attrs;
for (var i = 0; i < all.length; i += 1) {
attrs = Array.prototype.slice.call(all[i].attributes);
for (var j = 0; j < attrs.length; j += 1) {
if (attrs[j].value === 'specificValue') {
matches.push(all[i]);
break;
}
}
}
However, I would really love to avoid analyzing every single html element like this. Any ideas?
Edit:
Thanks for all the help so far. Before too many people give alternate suggestions I should explain what this is for. Basically, it's an experiment. The idea was that I might be able to create live object-to-dom databindings like what you get in Ember.js but instead of having to compile templates, you could just use regular html attributes and have a syntax marker in the value itself that a binding should be created. For example: . I figured this might be fun if there was an efficient way to select relevant elements on the fly. Clearly I know a loop has to happen somewhere. However, if the browser is running a native iteration, I'd prefer that over my own JavaScript loop. I just wasn't sure if there was some "secret" selector syntax I wasn't aware of or if anyone could think of any other cool tricks.
I wouldn't worry too much about performance at this point, but focus on code efficiency. If you don't want to incooporate any jQuery, and just use vanilla JS, then I would just store your attributes values in a class name. For example, if you have a following HTML element:
<div class="something" yo="1"></div>
I'd put entire attributes and values in a class name like
<div class="something yo1"></div>
Then you can simply use already built-in method to select every elements with the class name specified above.
var elems = document.getElementsByClassName("yo1"); //make sure to cache these selected elems in a variable.
console.log(elems);
If you want to use jQuery, things get easier, because you can simply select element by attribute selector and it works across all browsers.
http://api.jquery.com/attribute-equals-selector/
If you don't search for it, you cannot find it. So, basically you need to iterate through all the elements.
However, you may use some simple logic to at least help you with the performance.
Define a context
For example, you may have a really long HTML but within there, you may have a DIV where only inside of that div you may have your elements with the value "specificValue". In this case, you know that what you are looking for only resides within this div and only search within it.
You still have to go through all the elements but this time not within the whole HTML but only within the DIV that you expect the values to be.
So to summarize whether you use jQuery or plain javascript, you still have to go through all the elements. The solution is to narrow down the searchable "area" by defining a context and only searching within that..
E.g.
<html>
<head>
<title>some title</title>
</head>
<body>
.
.
<div class="searchable">
-- your elements that may have the value you will search
</div>
.
.
.
<div class="searchable">
-- your elements that may have the value again.
</div>
</body>
</html>
Mind you - you will have to itereate through all the elements again to find the divs with the class name "searchable". With jQuery $('.searchable') also does this. But you can also define a context for that and say $('.searchable', 'body') to narrow down that search area too..
I read through several threads without find a clear answer.
I'm using a JavaScript library (Drinks.js) to put several widgets on my webpage.
The following code will add one single item to my div element pnlThermo:
function create(item) {
var thermo = Drinks.createElement('display');
thermo.setAttribute('id', item);
thermo.setAttribute('label', item);
Drinks.appendChild('pnlThermo', thermo);
}
Well, now I want to add several items to the same div element. No matter if I use a for cycle or call the function explicitly only the first item will be rendered. For example:
create('T1');
create('T2');
create('T3');
leads to show T1 only.
Perhaps I missed something, I'm quite new to JavaScript programming.
Thanks in advanced.
The reference manual ( http://goincompany.com/DTManual01.pdf ) says :
After you have created the HTML element, you have to append it to an
HTML container. In order to do this you have to use the appendChild
function, provided by the Drinks class. Drinks.appendChild('body',
gauge); 'body' is the id of the HTML container. If the parent is an
instrument, this function doesn't work. We have to use the appendChild
method of the instrument, but we'll see this later.
Seems to imply that the first parameter needs to be an HTML tagname, which makes little sense
but then the library is a little wierd IMHO.
I am trying to access HTML elements by their id from an array of HTML Elements. I created this array using the getElementsByTagName and I am trying to access these elements like this: arrayName.getElementById("theId").
Basically this is what I am trying to implement:
In a Javascript function triggered by an onchange event I receive the reference to the element causing the trigger. Since its a table structure I get the reference to a <td> element.
Now I want to access all the other elements of the <tr> in which that <td> is, using the id of each individual element.
A small replica of my code:
function chngFunction(theTd){
var thisRow = theTd.parentNode;
var inputs = thisRow.getElementsByTagName("input");
alert(inputs[0].value);///////////Currently what I am doing////
alert(inputs[1].value);///////////Currently what I am doing////
.
.
.
//////// What I would like ////////
//// alert(thisRow.getElementById("myId").value); // or something like that////
/////////////// OR ///////////////
//// alert(inputs[].getElementById("myId").value); // or something like that////
///////////////////////////////////
This is what I want because, currently if I make any structural changes to my jsp, I have to make changes to js also (that can leave bugs). So using ids to access individual elements would be great.
Please help me out.
By definition, id values are unique throughout the entire document. So there is no HTMLElement#getElementById that retrieves elements by ID from only that element's descendants. Instead, there's document.getElementById that looks for them globally (since, again, id values are globally unique in the document). So if you're using id values:
alert(document.getElementById("myId").value);
You could use querySelector API.
This should work:
thisRow.querySelector('#myId');
And if your element ids are unique across the document (as they should be), you can just do document.getElementById.
getElementById is a method of the document object, not nodes, so you must use it this way: document.getElementById('id'); .
of course, this will only work if the HTML elements are attached to the DOM tree. In case they are'nt, you should use a selector API. like Sergio is suggesting in his answer.
I am creating an array of div tags inside the player table div. I'm getting all div tags with class .players. The divs with class name .players have input fieds and a link field inside. I want to be able to manipulate these (remove, add class, etc...)
What I thought would work would be something like:
$(divarray[j]+' .link').hide();
$(divarray[j]+' a').remove('.link');
But it's not working. Any thoughts? I'm sure it's something simple but it's my first time at JS :)
var divarray = $('#player-table > .players');
for( var j = 0; j < 10; j++){
$(divarray[j]).removeClass("players");
$(divarray[j]).addClass("selected_players");
$('#debug').append(divarray[j]);
$(divarray[j]+' a').hide();
}
First of all, you cannot just concatenate jQuery objects or DOM nodes with strings to create new selectors. jQuery provides methods for this kind of situations, where you already have an object or DOM node and want to find other related nodes.
Second, with jQuery there are much better ways to process a set of elements. Here is your code in more jQuery-like way. This is just an example, because I don't know the HTML structure. You have to adjust it so that it selects and applies to the correct elements.
$('#player-table > .players').slice(0,10) // gets the first 10 elements
.removeClass("players") // removes the class from all of them
.addClass("selected_players") // adds the class
.find('a').hide().end() // finds all descendant links and hides them
.appendTo('#debug'); // appends all elements to `#debug`
As you maybe see, there is only one semicolon at the last line. That means this whole code block is just one statement, but splitting it up over several lines increases readability.
It works because of the fluent interface, a concept which jQuery heavily makes use of. It lets you avoid creating jQuery objects over and over again, like you do ($(divarray[j])).
Another advantage is that you can work on the whole set of elements at once and don't have to iterate over every element explicitly like you have to do with "normal" DOM manipulation methods.
For learning JavaScript, I recommend the MDN JavaScript Guide.
jQuery has a couple of tutorials and a very good API documentation.
Read them thoroughly to understand the basics. You cannot expect to be able to use a tool without reading its instructions first.
Try this istructions
$(divarray[j]).find('.link').hide();
$(divarray[j]).find('a').remove('.link');
Try also
$(divarray[j]).find('.link:first').hide();
If you need to work only on the first element
Hope it helps