javascript - remove element/node with no ID and specific content - javascript

I'm struggling to decipher a way to remove several specific href elements which contain no IDs and are children of individual parents with no IDs.
The best I can manage is identifying the four offending, out of 8 or 9 href tags (and the number may vary), by a specific word within the URL itself. For this, I do the following:
<script language=javascript>
var xx = document.getElementById('theID').getElementsByTagName('a');
var ptn=/\=media/;
for(var i=0; i<xx.length; i++) {
if(ptn.exec(xx[i])){
alert(xx[i]);
}
}
</script>
Of course all this gives me is the four specific URLs within the href where "=media" is present. Now, somehow, I need to be able to remove either these href elements, or their parent elements (which happen to be unordered list tags). It's not until I get a level higher (table cell) that I gain access to an element ID, or anything distinguishing besides a particular word within the URL itself.
I'm open to any approach at this point - PHP may be an option (I really haven't explored this yet), but for this, javascript was my first logical choice. I can't tamper with the page that generates the links directly, only a secondary page which gets included at page load time.
Any pointers on how to solve this??
======================== final solution =====================
<script language=javascript>
var xx = document.getElementById('theID').getElementsByTagName('a');
var ptn=/\=media/;
for(var i=0; i<xx.length; i++) {
while(ptn.exec(xx[i].href)){
alert(xx[i]);
xx[i].parentNode.removeChild(xx[i]);
}
}
</script>

You don't need the ID to remove an element. You only need a reference to the element (which you seem to have).
instead of this:
alert(xx[i]);
try this:
XX[i].parentElement.removeChild(xx[i]);

You can call removeChild() on the parent element, like so:
xx[i].parentNode.removeChild(xx[i]);
As a side note, your regular expression isn't being executed on the href property. Change your if statement to:
if(ptn.exec(xx[i].href)){

var parent = xx[i].parentNode;
parent.removeChild(xx[i]);
http://www.onlinetools.org/articles/unobtrusivejavascript/chapter2.html has some nice examples of similar operations (scroll down).

Related

Document.querySelector returns a NULL value - script is at bottom of page

I am trying to get the patientNumber (ClinicA100-PF-TR1-P1) using querySelector. I keep getting a NULL value. The patientNumber is at the top of the page and the script is at the bottom. Even after the page is loaded, I click a button that runs the function and it still returns a NULL value.
Here is a screenshot of the selectors (https://recordit.co/IypXuuXib0)
<script type="text/javascript">
function getPatientNumber(){
var patientNumber = document.querySelector("patientNumber");
console.log(patientNumber);
console.log("hello");
return patientNumber;
}
var patientNumber = getPatientNumber();
console.log(patientNumber);
_kmq.push(['identify', patientNumber]);
</script>
Thank you for any help you can provide.
ADDITIONAL HTML INFORMATION:
I am using Caspio (database management software) to create this HTML code. I don't know if that may be the cause of the issue. Here is the HTML CODE.
<p class="sponsorName" id="sponsorNameID">[#authfield:User_List_Sponsor_Name]</p>
<p class="clinicNumber" id="clinicNumberID">[#authfield:User_List_Site_Number]</p>
<p class="protocolNumber" id="protocolNumberID">[#authfield:User_List_Protocol_Number]</p>
<p class="patientNumber" id="patientNumberID">[#authfield:User_List_Patient_Number]</p>
You are missing a dot.
var patientNumberNode = document.querySelector(".patientNumber");
var patientNumber = patientNumberNode.innerText;
if you select the item with class".", if you select with id, you should use"#".
var patientNumber = document.querySelector(".patientNumber"); // class select
var patientNumber = document.querySelector("#patientNumber"); // id select
Your selector is incorrect. It should be
var patientNumber = document.querySelector(".patientNumber");
Why is it failing:
When you use patientNumber as the selector, JavaScript looks for an element with a name of patientNumber. Since that's not the case, and you are looking for an element with a class of patientNumber, you need to use the . notation.
Addon Suggestion (can be ignored):
Since you are also using IDs, consider using document.getElementById() as it is faster than using document.querySelector().
Note that if you use document.getElementById(), your .patientNumber selector won't work. You need to write it as
document.getElementById('patientNumberID');
//ID based on the screenshot of the DOM you've shared
While the code is at the bottom of the page, and the element is at the top, it is not loaded asynchronously as it comes from a third party database. i put a delay in the getPatientNumber() and it works now.

How to check if link is present on a page with Jquery?

I have this link on my web page:
Terms and conditions
I want to use Jquery to check whether this specific link is present or not on the web page. I know how to check if text is present on a page, but am struggling a little with links. If it helps, it is only the terms-conditions-mywebsite bit that I need to use (as mywebsite changes depending on who is using the site).
The class is footer so I have tried $('.footer:contains("terms-conditions") but this doesn't seem to work. Any pointers would be appreciated, thanks so much :)
Edit: I need to check that the actual specific contents of this links is present, rather than the text 'Terms and conditions'
You should check the value of href attribute. You can use Attribute Contains Selector [name*=”value”] which select elements that have the specified attribute with a value containing a given substring:
The following should work:
if($('a[href*=terms-conditions]').length){
//exist
}
OR: Check the link string directly
if($('a:contains("Terms and conditions")').length){
//exist
}
I would look at doing this with Javascript, as it's very straightforward and means you are not reliant on JQuery should you wish to remove JQuery from the site at a later date.
// get <a> elements
var links = document.getElementsByTagName('a');
// loop through each <a>
for (var i = 0; i < links.length; i++) {
// get each href
var hrefs = links[i].getAttribute("href");
// check href against the one you want
if (hrefs == "https://www.google.com") {
// check content of link
console.log('link content:', links[i].innerHTML)
}
}

Eliminate undefined TypeError in self-executing anonymous function

I have a script that gives me the following error: 'TypeError: clickables[ic] is undefined' when I'm checking it with Firebug/in browser consoles. I'm a javascript beginner, who is trying to learn how to do things in vanilla javascript, and so I'm looking specifically for a solution that is just that.
The question: How do I get rid of/silence the undefined TypeError?
What the script should be doing:
I'm using this to reveal hidden elements, whose display attribute is set to none. The script should be getting all the instances of a particular class in a document, .item-reveal, joining that with a unique ID that each item having that class is given, to form a new class to search for via getElementsByClassName. The items with the .item-reveal class are items that are clicked on, the item that is unhidden/revealed has the .ID-reveal-item class (the unique ID of the clickable element followed by the .item-reveal class name reversed, for a simple convention). The ID isn't used for stying at all, it's merely to create a unique class based on a naming convention that can be applied to any pair of elements: one that is clicked on, one that is unhidden/hidden via creating/changing a style for the display attribute.
What the script does:
Currently, the script actually reveals the items onclick, and hides them again on subsequent clicks, and it works with multiple items. So, it kind of, basically, works. I just can't figure out the 'TypeError: clickables[ic] is undefined' issue and how to get rid of it. I get it in several browsers when using developer tools.
The script is an attempt at a self-executing anonymous function sort of thing, so I know the convention is a bit different, but I'm wanting to stick with it so I can apply it to other uses down the road. The article that inspired it is found here:
http://esbueno.noahstokes.com/post/77292606977/self-executing-anonymous-functions-or-how-to-write
EXAMPLE:
HTML
<!-- Item to be clicked, with unique ID -->
<h3 class="item-reveal" id="plan-1">Click for special pricing!</h3>
<p>An introductory paragraph...</p>
<!-- Hidden item to be revealed, will always have a unique class -->
<p class="plan-1-reveal-item">Special, this month only: $49.99</p>
<h3 class="item-reveal" id="plan-b">Click for special pricing!</h3>
<p>An introductory paragraph...</p>
<p class="plan-b-reveal-item">Special, this month only: $29.99</p>
CSS
/* Init - hide/unhide onclicks */
.item-reveal {cursor:pointer;}
[class$="-reveal-item"] {display:none;}
/* Halt - hide/unhide onclicks */
javascript:
var clickables = document.querySelectorAll('.item-reveal');
var clickCount = clickables.length;
(function () {
var Reveal = {
swapThis: function () {
for (var ic = 0; ic <= clickCount; ic += 1) {
// Next line seems to create the error message.
clickables[ic].onclick = function (unhideHide) {
var hidden = this.id;
var findClass = hidden += '-reveal-item';
var revealSwap = document.getElementsByClassName(findClass);
for (rn = 0; rn < revealSwap.length; rn++) {
revealSwap[rn].style.display = (revealSwap[rn].style.display == 'block') ? 'none' : 'block';
}
}
}
}
}
Reveal.swapThis();
}) ();
The script is linked via a SCRIPT tag, just prior to the closing BODY tag. I have tried it with both Async and Defer attributes, with and without other scripts in an HTML document, and the result is the same. I tried adding an event handler to ensure it wasn't something with the DOM loading still ongoing, but I'm not sure how to really test for that to see if it was actually doing anything. Unit testing is something that I'm just starting to attempt familiarizing myself with.
I'm trying to knock the dust off skills after several years in a completely unrelated industry, so the last year has been all about catching up on web development technologies, learning responsive design and HTML5 data stuff, and trying to learn javascript. I've searched, read, and bought several ebooks/books, and this is one of the few times I've run into something I just can't figure out. I imagine it's probably something simple and obvious to someone with formal programming/scripting knowledge, but I was an eBusiness major and networking, marketing, server/systems support, cabling, HTML/CSS, etc., are where I'm comfortable. Any help is greatly appreciated, but keep in mind that I'm trying to implement this in an environment/project that will have no jQuery, by choice. Thanks!
You are going off the end of the list with this:
for (var ic = 0; ic <= clickCount; ic += 1)
Change it to this:
for (var ic = 0; ic < clickCount; ic += 1)
clickCount is the length of the list so since it's 0 based indexing, clickables[clickCount - 1] is the last element in the list. You were trying to access clickables[clickCount] which does not exist.

change part of a link with javascript in a specific div only

Hi I need to edit some links on a page. Using the below code works but causes other problems on the page. I need the code to only affect elements with a certain input id. I also can't just replace the links as a query will be dynamically added to the end of each link. So in summary i just need to replace parts of all links with an input id "btnViewDetails". Any help would be great I'm very stuck. Cheers
<script language="javascript">
document.body.innerHTML = document.body.innerHTML.replace(/JobSeekers/g,'mobile');
document.body.innerHTML = document.body.innerHTML.replace(/JobPositionDetail.aspx/g,'JobPositionDetail_Mobile.aspx');
</script>
var someVariable = document.getElementsByClassName('btnViewDetails');
(you should use class instead of ID, if it is not a unique value).
someVariable is now an array holding all elements with class name btnViewDetails.
Now replace the text you want to replace only on the href values of you elements (you will have to loop over them):
for (i = 0; i < someVariable.length; i++) {
someVariable[i].href // do your replaces here
}

Why does replaceChild() behave oddly when replacing one kind of element with another?

I am relatively new at javascript, and found an interesting behavior that I can't explain today. I have a custom <hr> (with an image) on a website, which displays oddly in IE7 and below. To overcome this, I wanted to use replaceChild() in combination with getElementsByTag(). Initially, I simply tried to loop over the list, so:
var hrules = document.getElementsByTagName('hr');
for (var i=0; i < hrules.length; i++) {
var newHrule = document.createElement("div");
newHrule.className = 'myHr';
hrules[i].parentNode.replaceChild(newHrule, hrules[i]);
document.write(i);
}
However, this does not work: it actually only gets half the elements, skipping every other one. Printing i gives half-integer values of the actual number of <hr> elements in the document (e.g. if there are 7 <hr/> elements, it prints 4. By contrast, the following does work:
var hrules = document.getElementsByTagName('hr');
var i = 0;
while (i < hrules.length) {
var newHrule = document.createElement("div");
newHrule.className = 'myHr';
hrules[i].parentNode.replaceChild(newHrule, hrules[i]);
document.write(i);
}
i is printed the same number of times as there are hrules in the document (but of course is always 0, since I'm not incrementing it), and the hrules are replaced correctly. I recognize that the while here might as well be while(true)--it's just going until it runs out of <hr> elements, but appears to stop after that (it's not printing any more 0s).
I've tried this with a number of different types of elements, and observed that this only occurs when replacing one kind of element with another. I.e., replacing p with div, span with p, etc. If I replace p with p, div with div, etc. the original example works correctly.
Nothing in the documentation I've found (w3schools, various Google search, here, etc.) suggests an obvious answer.
What is going on here? First, why does the second example I offered work - is replaceChild() iterating over the elements automatically? Second, why is the behavior different for different types of element?
document.getElementsByTagName is a live access to all the HR elements in the document - it's updated whenever you change the document. You don't get a snapshot of all the HRs in the document whenever you call it.
So, with the first code, you are both incrementing i and reducing the size of hrules.length each time round the loop. This explains why you only see half the steps you expect.
Here's the solution I ended up using, in case anyone else (like #Pav above) is curious.
var hrules = document.getElementsByTagName('hr');
/* Each repetition will delete an element from the list */
while (hrules.length) {
var newHrule = document.createElement("div");
newHrule.className = 'ieHr';
/* Each iteration, change the first element in the list to a div
* (which will remove it from the list and thereby advance the "head"
* position forward. */
hrules[0].parentNode.replaceChild(newHrule, hrules[0]);
}
Essentially, what happens is you get a list of all the hrules in the document. This list is dynamically updated as you interact with it (see Matthew Wilson's answer). Each time you change the first element of the list to a div, it gets removed from the list, and the list is updated accordingly. The result is that you simply need to act on the first element of the list each time until the length of the list is 0.
That's admittedly a little counterintuitive, but it's how the list works.

Categories