Inject Code via Jquery Around specific Content - javascript

I'm having a bit of a quarrel with jQuery. I'm trying to inject a span with a specific class around a part of the content on an HTML page.
For example, this is the html I have:
<td class="">4 view</td>
And what I want is
<td class=""><span class="num_cell">4</span> view</td>
I feel this may be easier than I'm making it -- can anyone help?

This should also work:
$('td').each(function(){
$(this).contents().first().wrap("<span class='num_cell'>");
})

if you only want to cover only textNode you should use .contents() which also returns textNodes as item.
Please check the documentation http://api.jquery.com/contents/ there is an example which is exact answer of your question.
$("p").contents().filter(function(){ return this.nodeType != 1; }).wrap("<b/>");
After your comment, I don t think you need a loop for this, can you try the below code?
$("td").contents().filter(function(){ return this.previousSibling == null && this.nodeType != this.TEXT_NODE; }).wrap("<span/>");
this.previousSibling == null means it is first if you want to check if it is the first element or not
Cheers.

Have a look at this http://jsfiddle.net/zkjyV/30/
$(document).ready(function() {
$("td").each(function() {
var $div = $(this);
var $a = $div.find("a");
$div.find(a).remove();
var number = $div.html();
$div.html("<span class='num_cell'>" + number + "</span>").append($a);
});
});​
I did it with a div so it would run in jsFiddle. But you can replace the div with a and it should work just fine :)
Here's the final version http://jsfiddle.net/zkjyV/33/

Wow.. lots of answers already, here's a pure javascript answer for what it's worth.. I added an ID to the cell to make it simple, but you could easily take it from there to make it generic..
HTML
<td class="" id="targetCell">4 view</td>​
JS:
//get the parent reference to cache and avoid requerying the DOM
var parentCell = document.getElementById('targetCell');
// get the value of the first node (in this case TextNode)
var result = parentCell.firstChild.nodeValue;
// remove the TextNode
parentCell.removeChild(parentCell.firstChild);
// create a new span
var newSpan = document.createElement("SPAN");
//just for testing
newSpan.style.backgroundColor = 'orange';
//populate the value
newSpan.innerText = result;
//inject before the first child
parentCell.insertBefore(newSpan, parentCell.firstChild);​
JSFIDDLE:
http://jsfiddle.net/RBhLB/1/

Related

Replace multiple links

I'm trying to replace multiple links but only the first one is replaced,
all the other remain the same.
function rep(){
var text = document.querySelector(".link").querySelector("a").href;
var newText = text.replace(/http:\/\/test(.*)http:\/\/main(.*)com/, 'http://google$2com');
document.querySelector(".link").querySelector("a").href = newText;
}
Any suggestions?
It's multiple a href links inside .link elements which I'm talking about.
Your mistake is in using querySelector, so document.querySelector(".link").querySelector("a") literally translates to: get me the first a inside the first .link;
Use querySelectorAll; and you can combine the two selectors:
Vanilla JS:
[].forEach.call(document.querySelectorAll('.link a'), function(a){
a.href = a.href.replace(/http:\/\/test(.*)http:\/\/main(.*)com/, 'http://google$2com');
});
Or, since you'll select items more often, a little utility:
function $$(selector, ctx){
return Array.from((ctx && typeof ctx === "object" ? ctx: document).querySelectorAll(selector));
}
$$('.link a').forEach(function(a){
a.href = a.href.replace(/http:\/\/test(.*)http:\/\/main(.*)com/, 'http://google$2com');
})
Or in jQuery:
$('.link a').each(function(){
this.href = this.href.replace(/http:\/\/test(.*)http:\/\/main(.*)com/, 'http://google$2com');
});
This doesn't use JQuery, and I've changed your regular expression to something that made more sense for the example. It also works when you run the snippet.
function rep() {
var anchors = document.querySelectorAll(".link a");
for (var j = 0; j < anchors.length; ++j) {
var anchor = anchors[j];
anchor.href = anchor.href.replace(/http:\/\/test(.*)com/, 'http://google$1com');
}
}
rep();
a[href]:after {
content: " (" attr(href)")"
}
<div class="link">
What kind of link is this?
<br/>
And what kind of link is this?
<br/>
</div>
<div class="link">
What kind of link is this?
<br/>
And what kind of link is this?
<br/>
</div>
Edit: Expanded example showing multiple anchor hrefs replaced inside multiple link classed objects.
Edit2: Thomas example is a more advanced example, and is more technically correct in using querySelectorAll(".link a"); it will grab anchors in descendants, not just children. Edited mine to follow suite.
If you intend to only select direct children of link class elements, use ".link>a" instead of ".link a" for the selector.
Try using a foreach loop for every ".link" element. It seems that
every ".link" element have at least 1 anchor inside, maybe just one.
Supposing every .link element has 1 anchor just inside, something like
this should do:
$('.link').each(function(){
// take the A element of the current ".link" element iterated
var anchor = $(this).find('a');
// take the current href attribute of the anchor
var the_anchor_href = anchor.attr('href');
// replace that text and achieve the new href (just copied your part)
var new_href = the_anchor_href.replace(/http:\/\/test(.*)http:\/\/main(.*)com/,'http://google$2com');
// set the new href attribute to the anchor
anchor.attr('href', new_href);
});
I did't test it but it should move you to the way. Consider that we
could resume this in 3 lines.
Cheers
EDIT
I give the last try, looking at your DOM of the updated question and using plain javascript (not tested):
var links = document.getElementsByClassName('link');
var anchors = [];
for (var li in links) {
anchors = li.getElementsByTagName('A');
for(var a in anchors){
a.href = a.href.replace(/http:\/\/test(.*)com/, 'http://google$1com');
}
}
I suggest to read the following post comment for some cooler methods of looping/making stuff foreach item.
How to change the href for a hyperlink using jQuery

Javascript - How can I replace text in HTML with text in script

I am new to javascript. I was thinking getelementbyid but i don't know how to make it work
Like the title, here is what I mean
For example I have in HTML:
<p>fw_93</p>
<p>fw_94</p>
<p>fw_93</p>
So what I want is to make script to replace those fw_93 fw_94 to what I want.
For example
Instead of displaying "fw_93" I want it to display "9.3". Same with fw_94 to 9.4
Replace fw_ with nothing, divide the number by 10:
Array.prototype.forEach.call(document.getElementsByTagName('p'), function(el) {
el.innerHTML = parseInt(el.innerHTML.replace(/[A-Za-z_]*/, '')) / 10;
});
<p>fw_93</p>
<p>fw_94</p>
<p>fw_93</p>
Okay so select the tags.
Loop over the collection
read the html
match the string
replace the html
var ps = document.querySelectorAll("p");
for (var i=0; i<ps.length; i++) {
var p = ps[i];
var txt = p.innerHTML; //.textContent
var updated = txt.replace(/.+(\d)(\d)/, "$1.$2");
p.innerHTML = updated;
}
<p>fw_93</p>
<p>fw_94</p>
<p>fw_93</p>
Using JQuery
Not sure why I did it with JQuery, guess I wasn't paying enough attention. No point in me re-writing as there are already good answers in JS. Though I will leave this in case it's of use to anyone that is using JQuery.
You can loop though each <p> element and covert the contents, something like this:
$("p").each(function() {
var text = $(this).html();
var text = text.substring(text.indexOf("_") + 1);
var text = text[0] + "." + text.substring(1);
$(this).html(text);
})
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<p>fw_93</p>
<p>fw_94</p>
<p>fw_93</p>
You may need to add validation depending on how reliable your input is.
Note that the code makes the following assumptions:
There will always be a _ followed by at least 2 digits
The . will always go after the first digit
Your HTML:
<p id="p1">init_value</p>
Your JS:
document.getElementById("p1").innerHTML = "new_value";

How to clone an element using class name and append it to the body

I am trying to learn how to clone an element using classname and append it to the body.
here is what i have done but i am not getting any output. is there anything wrong ?
HTML:
<div class="check">hello</div>
CSS:
.check {
top: 100px;
}
JavaScript:
var elem = document.getElementsByClassName('.check');
var temp = elem[0].clonenode(true);
document.body.append(temp);
JSFiddle Link:
http://jsfiddle.net/hAw53/378/
if not JS, jquery solution is also welcomed.
You were almost there:
var elem = document.getElementsByClassName('check'); // remove the dot from the class name
var temp = elem[0].cloneNode(true); // capitalise "Node"
document.body.appendChild(temp); // change "append" to "appendChild"
<div class="check">hello</div>
You have 3 errors. Correct code:
var elem = document.getElementsByClassName('check'); // check, not .check
var temp = elem[0].cloneNode(true); // cloneNode, not clonenode
document.body.appendChild(temp); // appendChild, not append
Demo: http://jsfiddle.net/hAw53/379/
There are a few issues with your code.
getElementsByClassName() takes a class name (check), not a selector (.check)
cloneNode() is spelled with a capital N (not clonenode())
appendChild() is the name of the DOM method for appending a child (not append())
Correct version:
var elem = document.getElementsByClassName('check');
var temp = elem[0].cloneNode(true);
document.body.appendChild(temp);
You can do:
$('.check').clone().appendTo('body');
You're code had errors. First you used class selector and not the class name. Then you used an undefined property(properties are case sensitive) and you've to use appendChild instead of append which is a part of jQuery. You're too much confused with native javascript and jQuery.
in Jquery it's very simple, you just need to define inside what the new element apears.
var elem = $('.check');
elem.clone().prependTo( "body");

Select element by content

Within javascript, are you able to target elements on a page via psuedo classes? For example:
<table id="loginInnerTable">
<tbody>
<tr>
<td colspan="3">
<span class="required">*</span><span> = required</span>
</td>
</tr>
<tr>
<td>User ID <span class="required">*</span></td>
</tr>
</tbody>
</table>
How would I target the 'User ID' text to change it with .innerHTML? This is an example of a form that I don't have access to the code itself, except via JS.
Otherwise, what is the best method?
You can always make use of DOM traversal and HTML DOM extensions. This depends on your actual markup though. In this specific case you can do the following:
Get a reference to the table:
var table = document.getElementById('loginInnerTable');
Get a reference to the second row:
var row = table.rows[1];
Get a reference to the first cell:
var cell = row.cells[0];
Change the value of the first child node (works because it is a text node):
cell.firstChild.nodeValue = 'Some new text';
Or iterate over all text nodes to find the right one (if you have mixed element and text nodes or the node you want to change is not the first child):
var node = cell.firstChild;
do {
if (node.nodeType === 3 && node.nodeValue.indexOf('User ID') > -1) {
node.nodeValue = 'Some new text';
break;
}
} while(node = node.nextSibling);
If you don't want to restrict your solution too much to the current structure (it might change from time to time), then iterating over all rows/cells and find the desired cell would be a more flexible approach. Karl-André Gagnon showed this in his answer.
How about something like this to select the element, then just use it as a reference to update using innerHTML
var userTD = document.getElementById('loginInnerTable').getElementsByTagName('tbody')[0].getElementsByTagName('tr')[1].getElementsByTagName('td');
I'm not sure how efficient it is, but it should do the trick.
As others have mentioned it's not massively reliable - as if the table structure changes (which you say is out of your control) you'll have to change your code to work again.
Here a simple code that will change the text :
var tdEl = document.getElementsByTagName('td')
for(var cpt = 0; cpt < tdEl.length; cpt++){
if(tdEl[cpt].innerHTML.indexOf('User ID') != -1){
tdEl[cpt].innerHTML = 'some text <span class="required">*</span>';
}
}
If you want to make it a function (to reuse the code) :
changeNode('td', 'User ID', 'some text <span class="required">*</span>')
function changeNode(node, text, replace){
var el = document.getElementsByTagName(node)
for(var cpt = 0; cpt < el.length; cpt++){
if(el[cpt].innerHTML.indexOf(text) != -1){
el[cpt].innerHTML = replace;
}
}
}
How would I target the 'User ID' text to change it with .innerHTML?
You won't. Of course you could do something like
var tab = document.getElementById('loginInnerTable');
tab.innerHTML = tab.innerHTML.replace("User ID", "something else");
but that would replace the whole table, crushing and re-parsing its DOM (and it won't work in IE, of course).
Instead, you will use DOM manipulation to get and change that text node:
var tab = document.getElementById('loginInnerTable'),
td = tab.rows[1].cells[0],
text = td.firstChild;
text.nodeValue = "something else";

How can I make greasemonkey search only within a table

Below is my code and currently it searches the whole webpage. I'm trying to figure out how to make it search only within a table. (There is only one table on the page).
Any help would be appreciated.
var TargetLink = $("a:contains('gg')");
var TargetSink = $("a:contains('u')");
if (TargetLink && TargetLink.length)
{
window.location.href = TargetLink[0].href;
}
else if (TargetSink && TargetSink.length)
{
window.location.href = TargetSink[0].href;
}
var TargetLink = $("table a:contains('gg')");
var TargetSink = $("table a:contains('u')");
EDIT:
You say there is only one table on the page. Do you absolutely know there will only ever be one table? Even if you think the answer is yes, I would try and add an id or class selector so that things won't break in the future.
Also, the following code can be simplified:
if (TargetLink && TargetLink.length)
to:
if (TargetLink.length)
Re: "could I combine those 2 variables into 1":
Use a comma in the selector, like so:
//--- Need more of the HTML structure for a better selector.
var TargetLink = $("table")
.find ("a:contains('gg'), a:contains('u')")
;
if (TargetLink.length) {
window.location.href = TargetLink[0].href;
}
If both kind of links are found, 'gg' will be used (first).

Categories