I'm using a web service to query a ticketing interface and pull back all support tickets that are open at any point in time, displaying them in a nice neat table within an iframe as part of our web application. My application is written in PL/SQL however I use this to construct my HTML pages and the content that is displayed within my iframe. My main issue is that because the tickets are made up of Email content, there is a lot of useless rubbish (mostly tags) and irrelevant text that is included at the top of the Email content which causes my interface to look trashy.
Within my code I am wrapping the main areas of content that I require in a table with an ID of "ticketsTable" and would like to remove any elements or content within the iframe only that occurs before this tickets table.
Usually I would use jQuery for this task:
$("#earliercontent").nextUntil("#ticketsTable").andSelf().remove();
however, our system is built using ExtJS so we wish to avoid any potential conflict the jQuery library could cause with this environment. I therefore need a way to process and loop through the contents of the iframe, removing all elements and text that occur before the ticketTable id therefore eradicating all of the unnecessary content.
I've already tried this:
var last = null;
var curr = $('#page1');
while (curr.attr('id') != 'ticketsTable') {
if (last != null) {
last.remove();
}
last = curr;
curr = curr.next();
}
if (last != null) {
last.remove();
}
Source: jQuery remove all elements until id='whatever' found
however, as the Email content is variable, there is no specific ID tag I can specify for the script to start at. Therefore, is there an alternative method I can use (without a library, just pure JavaScript) to remove all elements and content before the ticketsTable?
I must stress that the contents of the ticketsTable must remain intact. It is only the content that occur before this within the body that I wish to remove.
http://jsfiddle.net/yJrb7/
var parent = document.getElementById("parent");
var stopID = "stop";
var length = parent.childNodes.length, j = 0;
for(var i=0; i < length; i++){
if(parent.childNodes[j].id != stopID){
parent.removeChild(parent.childNodes[j]);
}
else{
j++;
}
}
When you remove a child node, the array is shifted, so if for example you need to remove two first nodes, then you would call removeChild for index 0 two times.
Related
I have an html form which when signed I'd like to create a number of copies of to display directly after one another. My poor cloning function looks like this:
function formCloner(numCopies) {
let cloneContainer = document.createElement("div");
cloneContainer.id = "formCopies";
for(i = 0; i < numCopies) {
// grab the whole html form
let html = document.getElementsByTagName("html")[0];
let htmlClone = html.cloneNode(true);
/*
* do some other stuff to the clone
*/
cloneContainer.appendChild(htmlClone);
}
document.body.appendChild(cloneContainer);
}
One of the big problems with this approach is that in the end all of the form elements copied over share the same ID. Which is bad. I thought about running through each child node and changing the IDs manually but that seemed like overkill. There must be a simpler answer, can anyone recommend a painless way to achieve the end result of having copies of the form appended to the document body?
This is pretty easy... Simple target all elements with IDs, and add _# to them. Also do the same on the for attribute, since they are the only real reason why you'd want to play with IDs in the first place.
htmlClone.querySelectorAll("[id]").forEach(elem=>elem.setAttribute('id',elem.getAttribute('id')+"_"+i));
htmlClone.querySelectorAll("[for]").forEach(elem=>elem.setAttribute('for',elem.getAttribute('for')+"_"+i));
I have to add a registered trademark symbol to all references to a brand, let's call it "SomeBrand" on a client site. Currently I have this:
function updateSomeBrand(){
var elements = document.getElementsByTagName('*');
for(el in elements){
if(["SCRIPT", "META", "HEAD", "STYLE", "IFRAME", "NOSCRIPT", "IMG"].indexOf(elements[el].tagName) < 0){
if(elements[el].innerText != undefined && elements[el].innerText.indexOf("SomeBrand") > 0){
console.log(elements[el].innerText);
console.log(elements[el].innerText.indexOf("SomeBrand"));
elements[el].innerHTML = elements[el].innerHTML.replace("SomeBrand", "SomeBrand®")
}
}
}
}
But it adds extra ® symbols after all references to SomeBrand, in some cases it adds six or seven. I'm not sure yet why. Is there a better way to go about this? There are a lot of references on different product pages, so I'd like to add some JS to the product page template instead of manually updating them.
You're calling .replace() in all elements, including container elements. That means that you first replace all of the HTML in the container, then replace it again for each child.
Instead, you should modify text nodes only. getElementsByTagName() equivalent for textNodes
This exercise will be to write a helper script that could theoretically be used on any web page to help identify the elements that contain text, simply by including your JavaScript file!
Define the script in a source file called highlightNodes.js.
This script should navigate every element in the DOM, and for each element in the body determine whether it is a element ( type 3) or not.
Now add to your script code to create a new child node for every non-text node encountered. This new node should take on the class " hoverNode" and innerHTML equal to the parent tag name. Define appropriate styles for that CSS class.
Now add listeners so that when you click on the newly created nodes, they will alert you to information about the tag name, so that when a node is clicked a pop- up alerts us to the details about that node including its ID and innerHTML.
The example picture that the teacher took it really poor quality, but I think you will still be able to see what's going on.
http://imgur.com/7XKs4U5
Here's the code I have so far: https://jsfiddle.net/vuku3qdu/2/
window.onload = function () {
var bodyNodes = document.getElementsByTagName("*");
for (var i = 0; i < bodyNodes.length; i++) {
if (bodyNodes[i].nodeType != 3) {
newChildNode = document.createElement("p");
newChildNode.className = "hoverNode";
newChildNode.innerHTML = bodyNodes[i].tagName;
bodyNodes[i].appendChild(newChildNode);
newChildNode.addEventListener("click", function () {
alert("Tag Name: " + newChildNode.tagName + " innerHtml: " + newChildNode.innerHTML);
});
}
i++;
}
};*
For some reason, this isn't working on Jfiddle correctly. It displays highlight nodes locally. My issue is that it isn't evaluating the nodeTypes properly. It is saying that they are all "1" for NodeType. I know this isn't correct and it's giving me too many of these highlight nodes. Also, it is skipping the "label" elements that are embedded within the Fieldset.
My last problem... I can't get the Highlight nodes to output the proper newChildNodes.innerHTML in the listener functions. It always gives me undefined.
I've logged all of the steps through the console and I know that it is evaluating the node types wrong, but I cannot figure out the correct command to do so.
Thanks Guys!
I have been assigned the task of cleaning up over 5,000 lines of CSS. During the development of this project, we basically just appended classes to this massive CSS file.
I am tasked with organizing classes according to their pages, and then prepending the page ID to them to make them only hit that page.
However, what makes this tedious is manually finding out what classes and ID's are in a page, and then organizing them.
Is there a way to "dump" all the classes from a stylsheet, ONLY on that page, into a file or something?
To get an array of classes/id's in use, loop over every element in the document and populate an array. Obviously this isn't very efficient, but considering the task at hand, i doubt that is a concern.
var idArr = [];
var classArr = [];
[].forEach.call(document.querySelectorAll("*"), function(element){
if (element.id && idArr.indexOf(element.id) == -1) {
idArr.push(element.id);
}
if (element.className) {
var tempClassArr = element.className.split(" ");
for (var i = 0; i < tempClassArr.length; i++) {
if (classArr.indexOf(tempClassArr[i]) == -1) {
classArr.push(tempClassArr[i]);
}
}
}
});
console.log(idArr);
console.log(classArr);
http://jsfiddle.net/QLmNf/1/
This will give you an array of ID's and an array of classes on the page. you would then need to compare this to the style declarations to find ones that match. This of course won't cut out declarations that use these id's and classes but don't actually match any elements on the page, you might be able to solve that problem with the audits tab suggested by #jordanforeman.
I was going through the method of removing html tags from the content extracted from a website.
It might contain instances like complete html tags tst
or broken ones like <div class="testClass" or class="testClass"> , Ive come up with a way of removing the complete tags, Can the partial tags be removed using javascript or jquery (regex way)???
The code that I used to remove complete tags are replace(/<(?:.|\n)*?>/gm, '')
This is very hard to do using regex even with a high level language. But you could inject the html into the current DOM or for example in a hidden iframe. Then you build a "node walker" to go down the DOM-Tree and collect the "inner text" of the HTML-Nodes. As long as the DOM represents them you get what you want using the native DOM-Parser.
I did this once and it worked like this:
var nodes = document.getElementsByTagName('BODY');
function nodeWalker(node) {
if(!node.hasChildNodes()) {
return;
}
for(var i=0; i<node.childNodes.length; i++) {
// filter by node type == 3 equals TEXT_NODE
if((node.childNodes[i].nodeType == 3) && node.childNodes[i].nodeValue.length > 0) {
// extract content in node.childNodes[i].nodeValue
}
// type == 1 equals ELEMENT_NODE
else if(node.childNodes[ i ].nodeType == 1) {
nodeWalker(node.childNodes[i]);
}
}
}
See http://www.w3schools.com/dom/dom_nodetype.asp for all possible node types!
Another way is would ne to use AJAX and a server side DOM-Parser.