I use jQuery to get values of presaved elements from some websites, using paths like this:
HTML BODY #bodyContainer #mainContentContainer #mainContent #productContentRight #swatchContent #colorSwatchContent SPAN
The problem i faced when the websites page contains tables and there are same element in another similar path such as:
/html/body/div/center/div/div[3]/div/table/tbody/tr[5]/td/div/table/tbody/tr/td/table/tbody/tr/td/table/tbody/tr[3]/td
In the last path as you can see that there are 5 tr which means that its possible to find the same element in another path.
I use the path as a selector for jQuery and jQuery will return array of elements, i don't know which one is the right element.
So my question is:
How to save the path for better later use? and how to parse this new path to be ready as a jQuery selector.
If the question is not clear please ask me and i will do my best to explain more.
I don't know why there are so many answers that you are using XPath because XPath was deprecated a long time ago and jQuery no longer supports it without the XPath compatibility plugin.
See Release Notes of 1.2 : http://www.learningjquery.com/2007/09/upgrading-to-jquery-12
XPath compatibility plugin : http://docs.jquery.com/Release:jQuery_1.2#XPath_Compatibility_Plugin
Just use $("#colorSwatchContent span") as your selector. Which is a css style seclector meaning find me all descendent span elements of an element with id colorSwatchContent. Since id's in html are unique identitfiers, this is about as specific as you can get.
$("#colorSwatchContent > span") will only select DIRECT descendents (immedieate children)
$("#colorSwatchContent > span:first") will select the first span direct descendent
In order to grab one specific element when there are many that match you should give the elements classes, for example give each table a class describing what is in it, then give each tr a class describing what the row is about. Then each td with a class describing the specific part of the row that it describes, for example:
<table class="person">
<tr class="john-doe">
<td class="name">John Doe</td>
<td class="phone-numbers">
<table class="phone-numbers">
<tr class="cell-phone">
<th class="label">Cell Phone:</th>
<td class="number">555-1234</td>
</tr>
<tr class="home-phone">
<th class="label">Home Phone:</th>
<td class="number">555-1234</td>
</tr>
</table>
</td>
</tr>
</table>
Once you have your elements properly described then you can use CSS style selectors in jQuery. for example getting just the td that has the home phone would be as simple as doing:
$('table.person tr.home-phone td.number');
Hope this gets you heading the right way.
One thing to note tho, If you have incredibly complex table structures you might want to rethink whether it needs to be in a table or not.
tr[5] doesn't mean there are 5 trs (there could be 10!), it means that it is selecting the 5th one.
It looks to me like you are using an XPath selector to get your elements... which jQuery supports.
if you have control of the HTML, the easiest way to select a specific element is to give it an id... which in your first example,
HTML BODY #bodyContainer #mainContentContainer #mainContent #productContentRight #swatchContent #colorSwatchContent SPAN
is equivilant to
#colorSwatchContent SPAN
Since jQuery supports xpath you could use firebug to get the specific xpath, and then use that in jQuery.
Just browse the source in firebug, right click any element, and then choose copy xpath.
Related
I am using gopherjs to accompish this task.
I only need to change data in one cell. But I have severally similar templates.
I can add data to any element by id. But in this case, I am wondering if I am doing something wrong.
Right now I am just getting the element by id directly, but I am wondering if I need to be more specific about the row, table and div.
I have the following table:
<div class="container">
<h2>Search results</h2>
<table class="table">
<thead>
<tr>
<th>Results</th>
</tr>
</thead>
<tbody>
<tr>
<td align="result" id="expirydata">John</td>
</tr>
</tbody>
</table>
</div>
I only need to change the epirydata cell. Do I need to give the row an id? Do I also need a table Id?
Disclaimer: I have never worked with gopherjs.
IDs in HTML are supposed to be unique within a web page. the function getElementById depends on it. If you need to programmatically modify always the same cell based on the same template occurring in multiple places within a page, here are your options:
have parametrized/configurable ID. Pass it into your template and getElementById accordingly. Upside: easy to implement. Downside: hard to maintain due to leaky abstraction and having to manage all the IDs outside the templates.
have a template builder method, which will accept a content as a function parameter and will output the template with already replaced content. Upside: implementation details encapsulated. Downside: with larger templates you degrade performance and might have to introduce caching of parameters if there will be multiple placeholders to fill into.
parametrize the template by putting ID into the top-level element in your template, e.g. table or a div. Don't use ID in the nested elements, rather use class to navigate within the ID element using the querySelector function. This gives you flexibility, maintainability and reusability.
I assume you use .innerHTML = 'content' approach. Beware of the XSS attacks.
Modern frameworks like react or angular go the 2) way and handle/offer the performance the optimizations as well as the security aspect out of the box. There might be other frameworks/view libraries which might be slimmer and/or work in coordination with gopherjs. Try to look for these.
const table = document.querySelector("table");
table.rows[1].cells[0].textContent = "changed_text";
//First find table by tagname or class name.
//then travel into table by its rows and cells number
I am using an ASP.NET MVC helper method to create a webgrid. I want to dynamically set the colors of a table row but I have no access to the td tag to change its properties or add an id.
So what I am trying to do from the backend is inject a script in the td's body to conditionally change its color. I have tried:
<script>$(this).css("background-color", "red !important");</script>
and this did not work. If this didn't work then I am not sure what else I can do as this seemed like the most direct approach; although I am a novice with javascript so I am looking for some help on this.
I have found other topic questions similar to what I am asking but the responses seems to mostly use contains, onclick, or make use of an id tag.
Basically if this was pure markup, and you had a table,
<table>
<tr>
<td>
how to insert a script here to change this current elements color
without know its id?
</td>
</tr>
</table>
You can use
<script type="text/javascript">
var allTD = document.getElementsByTagName("td");
</script>
Wich will return a collection of all the td elements in your HTML file.
Then, all you have to do is to iterate over the collection and change the style of the elements.
More info at Mozilla Developer Network.
Basically I'm fairly new to Javascript/Jquery and am looking for a more full proof way of adding a class to a TD that contains an <a> tag.
At the moment 90% of my dataTables contain a final column with tags in the TD's containing: a Details button, a Delete Button and an Edit button.
So far I have got it working using the following code:
$('table.dataTable td:contains("Details")').addClass('tdButton');
What bothers me is that there's potential for the final column not to feature the text containing "Details" in the near future. So id rather bind it to the element.
Here is a brief bit of my html for the TD's:
<td class="tdButton">
<a class="linkButton tdButton" href="/Aptitude2/TestletBank/Details/0da14b39-8fae-e311-9403-00155d0a0c32" id="linkButtonDetails_0">Details</a>
<a class="linkButton tdButton" href="/Aptitude2/TestletBank/Edit/0da14b39-8fae-e311-9403-00155d0a0c32" id="linkButtonEdit_0">Edit</a>
<a class="linkButton linkButtonDelete tdButton" href="/Aptitude2/TestletBank/Delete/0da14b39-8fae-e311-9403-00155d0a0c32" id="linkButtonDelete_0">Delete</a>
</td>
You can use has()
$('table.dataTable td').has("a").addClass('tdButton');
or :has()
$('table.dataTable td:has(a)').addClass('tdButton');
both selects elements which contain at least one element that matches the specified selector.
You can ensure that using :has selector with id selector for anchor tag detail in it:
$('table.dataTable td:has(#linkButtonDetails_0)').addClass('tdButton');
Working Demo
I'm trying to use AngularJS to create a table of a list of events. But each event has a type, and events of different types have drastically different contents, and some types also generate more than one row.
In a perfect world, I'd do this:
<tbody>
<ng-repeat="event in events">
<ng-switch on="event.type">
<ng-switch-when="type1">
<tr>
...
</tr>
<tr>
...
</tr>
</ng-switch-when>
<ng-switch-when="type2">
<tr>
...
</tr>
</ng-switch-when>
...
</ng-switch>
</ng-repeat>
</tbody>
but this won't work because most browsers will discard or relocate the ng tags to enforce that the tbody only contains trs.
The only solution I've seen to related problem (How to use ng-repeat without an html element) is to have multiple tbody elements; I'd prefer not to do that, but even if I do this, giving the tbody the ng-repeat and ng-switch attributes, I still have the problem that I can't wrap multiple trs in a single ng-switch-when.
Is there a way to do this in AngularJS, or is this impossible?
I've run into this problem, best advice is don't use table:
just do a parent div id with * ammount of child div classes just like they are tr's and td's...
i haven't checked this in angular source but i'm assuming that the table elements aren't intertwined somehow, who knows..
Maybe the best option would be a directive that generates the appropriate markup based on your type1/type2?
You could probably also do it with ng-hide/ng-show, though that would generate extra unnecessary markup
I wrote a javascript function that uses the innerHtml of a named div (that occurs immediately after the script) for each row as output. the problem is, if I use $('divname'), it always finds the first instance, not the nearest. What's the simplest way in prototype to target the nearest "divname" div?
eg (note, I'm using Grails, hence the <g:...> tags):
<g:each ... >
<tr>
<td colspan = "4">
<g:javascript>
...
$('outputdiv').innerHTML = theoutput;
</g:javascript>
<div id='outputdiv' /> //target THIS instance, not the first!
</td>
</tr>
</g:each>
EDIT: I initially read the question as pertaining to jQuery, but the idea should be the same for Prototype or any other library.
Seems like this is what you want to do:
$('#outputdiv').html(theoutput);
Since IDs must be unique in a document, #outputdiv would be the selector that you want. If you're using outputdiv for multiple IDs, you're not using valid markup and you'll get unpredictable results.
If you need a bunch of outputdivs, you'll want to make it a CSS className, and probably do something with jQuery's closest( ) or nextAll( ) or prevAll( ).
Also, note that your function is going to attempt to set the innerHTML of an element that does not yet exist. You'll probably want to run it onDOMReady or include your script after the element is closed and "ready" in the DOM.
// Assuming theoutput is available in this context
$(document).ready(function(){ $('#outputdiv').html(theoutput) });