I'm just getting started in programming and somehow can't come up with any sensible approach to the following problem, so any help would be greatly appreciated! I have a .html file structured like this:
<head>
<title>ABC</title>
</head>
<body>
<div class="norm">
...
<span class="jnenbez">13</span>
....
<div class="Absatz">text</div>
<div class="Absatz">text</div>
<div class="Absatz">CITE HERE**</div>
The "norm" div is the one parent node. The "jnenbez" span and the "Absatz" divs are inside the "norm" div, but how deeply they are nested can vary. Now I want to cite the "CITE HERE" area, meaning to generate the output of "jnenbez 13 Absatz 3 ABC" - meaning getting the text content of the "jnenbez" span of the same "norm" div, getting the index number of the "Absatz" div, since it is the third child "Absatz" of the "norm" div and getting the content.
1) How could I give this string to the user, so he could copy paste it somewhere else? It seems it is not easily possible to modify the copy+paste behavior of Firefox. An obvious solution would be to put the output in brackets like [jnenbez...] at the end of each divs text content, but that would reduce readability of the html...
2) Is it even possible to automatically generate this output via JQuery?
Not sure about a good way to store/display the info.
Also, unsure of what other mark-up you would have in the class='norm' container. This is vitally important and impacts entirely the shape of the useful solution.
I've assumed a particular structure - one that says the first contained span is one of interest. Another assumption is that the only divs in the container are of interest and need to be counted.
I'm sure you can break it easily enough. :D
<!DOCTYPE html>
<html>
<head>
<script>
function onBtnPress(element)
{
var result;
var cont = element.parentNode;
var span = cont.getElementsByTagName('span')[0];
result = span.className + " ";
result += span.innerHTML + " ";
var divList = cont.getElementsByTagName('div');
result += divList[0].className + " ";
result += divList.length+" ";
result += document.title;
cont.getElementsByTagName('p')[0].innerHTML = result;
}
</script>
<title>ABC</title>
</head>
<body>
<div class="norm">
<span class="jnenbez">13</span>
<div class="Absatz">text</div>
<div class="Absatz">text</div>
<div class="Absatz">CITE HERE**</div>
<button onclick='onBtnPress(this);'>click me</button>
<p>[string here]</p>
</div>
<div class="norm">
<span class="Crapple">8</span>
<div class="ipod">worst</div>
<div class="ipod">music</div>
<div class="ipod">player</div>
<div class="ipod">I ever</div>
<div class="ipod">bought</div>
<div class="ipod">CITE HERE**</div>
<button onclick='onBtnPress(this);'>click me</button>
<p>[string here]</p>
</div>
</body>
</html>
Related
I have links embedded inside .media-body .media-heading in the HTML example. I'm wanting to write JS to remove any link where the text does not start with the value attribute in the input element, in this case "A"
I've done a manual version below that checks the first A tag and manually removes the other A tag on the click of a button if the text doesn't start with "A". I need this to somehow loop through and do this automatically on page load but not sure how I do that. Any help is appreciated.
<!DOCTYPE html>
<html>
<body>
<input type="text" name="search" value="A" class="searchbox">
<div class="media-body">
<div class="media-heading">
A doc beginning with A
</div>
</div>
<div class="media-body">
<div class="media-heading">
Doc beginning with D
</div>
</div>
<button onclick="startFunction()">Remove wrong doc</button>
<script>
function startFunction() {
var az = document.getElementsByTagName("input")[0].getAttribute("value");
var getstart = document.getElementsByTagName("a")[0].innerHTML;
var searchletter = getstart.startsWith(az);
var myobj = document.getElementsByTagName("a")[1];
if(searchletter = az)
{
myobj.remove();
}
}
</script>
</body>
</html>
The second part of your question as how to do this automatically on page load is answered rather quickly. Conveniently you already wrapped the functionality inside it's own function - startFunction(). So all you have to do is execute that function after the <body> definition of your html code.
The first part isn't much more difficult as you also almost have anything you need set up yet. The only thing that's missing is looping over the HTMLCollection - more or less an array - retrieved by executing document.getElementsByTagName("a") using a simple for-loop.
There's a catch though: as you loop over the HTMLCollection and eventually remove an object from the DOM using .remove() you're ultimately changing the collection too. In other words, if you remove an object, the list shrinks by one element. To compensate your loop needs to start with the initial number of elements and decrement by one.
Here's an example:
function startFunction() {
let az = document.getElementsByTagName("input")[0].getAttribute("value");
let elements = document.getElementsByTagName("a");
let element;
for (let a = elements.length - 1; a >= 0; a--) {
element = elements[a];
if (!element.innerHTML.startsWith(az)) {
element.remove();
}
}
}
startFunction();
<input type="text" name="search" value="A" class="searchbox">
<div class="media-body">
<div class="media-heading">
A doc beginning with A
</div>
</div>
<div class="media-body">
<div class="media-heading">
Doc beginning with D
</div>
<div class="media-body">
<div class="media-heading">
Something completely different
</div>
</div>
I am trying to get a form to be fed onto my HTML page and then use tags to edit the layout. It will take information from my database and have it displayed in a form in the form of a value.
I am having constant issues with it saying that I have syntax errors. It happens everytime I add a div tag into the feed.
I have tried many things, but the only thing that gets this code to work consistently is when I take out all tags.
At this point, I am wondering if there is a better way to do this. Any help would be appreciated
HTML
<!DOCTYPE html>
<html lang="en">
<head>
<!-- information -->
<body>
<div class="feedContainer" id="nfeed">
</div>
<script src="managePosts.js"></script>
</body>
</html>
JS
var db = firebase.firestore();
const HTMLFEED = document.getElementById("nfeed");
//works
db.collection("trips").where("flag", "==", true).where('userID', "==", /*localStorage.getItem('userID') */ "101010101").get().then(function (querySnapshot) {
querySnapshot.forEach(function (doc) {
var fullName = doc.data().fullName;
HTMLFEED.innerHTML += " \
<form> \
<img src='circleProfile.png' alt='User photo'> \
<div class='name'> <p>" + fullName + "</p></div>\
<div id='updatingForm'> \
</form>";
});
});
You need to add a backslash to every line, even the empty ones.
You could also just remove the empty ones, but the best solution I could think of would be to use Template literals:
HTMLFEED.innerHTML += `
<form>
<img src='circleProfile.png' alt='User photo'>
<div class='name'> <p>${fullName}</p></div>
<div id='updatingForm'>
</form>`;
I know the problem here is because they both share the same id for input and for div. is there a way to specify the id of the specific div clicked like "this". without having multiple ids in my code
<!DOCTYPE html>
<html>
<head>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.0/jquery.min.js"></script>
<script>
$(document).ready(function() {
$(this).on("click", ".descrip", function() {
$(this).next('.def').slideToggle("slow");
});
});
function addDef() {
//window.alert (1);
var def = document.getElementById("defInput").value;
//window.alert (def);
document.getElementById("addf").innerHTML += "<div class= 'descrip'> descrip </div>";
document.getElementById("addf").innerHTML += "<div class= 'def'> " + def + " </div>";
}
</script>
</head>
<body>
<div class="descrip"></div>
<div class="def"></div>
enter def for apple:
<input type="text" id="defInput">
<br>
<br>
<button onclick="addDef()">ADD</button>
<div id="addf"></div>
<div class="descrip"></div>
<div class="def"></div>
enter def for orange:
<input type="text" id="defInput">
<br>
<br>
<button onclick="addDef()">ADD</button>
<div id="addf"></div>
</body>
</html>
The value must be unique amongst all the IDs in the element’s home subtree and must contain at least one character.
W3C HTML 5.1 topic 3.2.5.1. The id attribute
Could you use class names rather than an id, then use document.getElementsByClassName instead?
<button onclick="addDef('addf-1')">ADD</button>
<div class="addf-1"></div>
<div class="descrip"></div>
<div class="def"></div>
enter def for orange:
<input type="text" id="defInput">
<br>
<br>
<button onclick="addDef('addf-2')">ADD</button>
<div class="addf-2"></div>
Then in your function:
function addDef(className) {
//window.alert (1);
var def = document.getElementById("defInput").value;
//window.alert (def);
document.getElementsByClassName(className)[0].innerHTML += "<div class= 'descrip'> descrip </div>";
document.getElementsByClassName(className)[0].innerHTML += "<div class= 'def'> " + def + " </div>";
}
NOTE: I am not advocating this method, but this is a simple fix to your issue. I am making the assumption you were not aware of the existence of any other way to retrieve a node in the DOM besides getElementById.
Directly from HTML5 Spec:
The id attribute specifies its element's unique identifier (ID). The value must be unique amongst all the IDs in the element's home subtree and must contain at least one character. The value must not contain any space characters.
An element's unique identifier can be used for a variety of purposes, most notably as a way to link to specific parts of a document using fragment identifiers, as a way to target an element when scripting, and as a way to style a specific element from CSS.
A possible solution is to change it to a class and then use the following nomenclature to target in your CSS or JS:
[class^="defInput-"], [class*=" defInput-"] {}
This will target any class that begins with defInput-
I'am building a Chrome extension that parses the entire DOM/HTML and replace any found email(multiple emails) with the following div:
<div class="email_tmp"> found_email <span>SAVE EMAIL</span></div>
EXAMPLE:
<body>
<div>Some Text...</div>
<div>text a#a.com text</div>
<div>Some Text...</div>
<p>More Text</p>
<div><div><span>text b#b.com text</span></div></div>
<span>Last text</span>
</body>
replaced to:
<body>
<div>Some Text...</div>
<div>text <div class="email_tmp"> a#a.com <span>SAVE EMAIL</span></div> text</div>
<div>Some Text...</div>
<p>More Text</p>
<div><div><span>text <div class="email_tmp"> b#b.com <span>SAVE EMAIL</span></div> text</span></div></div>
<span>Last text</span>
</body>
How can I search and replace the found email by the entire div and the string found_email by the email too?
I want to replace only the found email(s) string, nothing more...
I really appreciate any help.
Here is the total solution for what your looking for
HTML
<div id="main">
sdfsdsdfsdfsdf a#a.com sdfsdfsdfsdfsdfsdf
</div>
JavaScript
var page_content = document.getElementById('main').innerHTML;
var found_email = "<div class='email_tmp'> found_email <span>SAVE EMAIL</span></div>";
//gives an array of the emails
var email = page_content.match(/([a-zA-Z0-9._-]+#[a-zA-Z0-9._-]+\.[a-zA-Z0-9._-]+)/gi);
//replaces the emails to your desired content
var result = page_content.replace(email, found_email);
//replaces the changed HTML back to the 'main' div
document.getElementById('main').innerHTML = result;
Here is the Fiddle
Update:
If you want to replace only the text without adding any class or tags to the content of the HTML, then it gets real complicated to write a vanilla script for the same. In that case I would highly suggest you to use this library which I found to be the perfect solution for your problem.
Its a library called findAndReplaceDOMText which uses inbuilt methods to solve the purpose. You just need to give the find(what to find) and replace(replacing HTML) like so,
findAndReplaceDOMText(document.getElementById('t'), {
find: /([a-zA-Z0-9._-]+#[a-zA-Z0-9._-]+\.[a-zA-Z0-9._-]+)/gi,
replace: '<div class='email_tmp'> found_email <span>SAVE EMAIL</span></div>'
});
You can obviously revert if you face any problems in implementing this library.
Also this a must read article for you - replacing-text-in-the-dom-solved
Slight update on #NikhilNanjappa 's original answer: my version is less efficient, but it will keep the actual email address and prepend the div and append the span and closing tags, based on the original answer.
var save_email_beg = "<div class='email_tmp'> ";
var save_email_end = " <span>SAVE EMAIL</span></div>";
var i = 0;
for (; i < email.length; i++) {
var new_string = save_email_beg + email[i] + save_email_end;
page_content = page_content.replace(email[i], new_string);
}
document.getElementById('main').innerHTML = page_content;
EDIT: Here's the JSFiddle for the following question.
http://jsfiddle.net/x28ojg6w/
So I'm trying to activate a template with JavaScript and it wasn't working for a while, and I finally fixed it by changing a For-In loop into a For loop in a seemingly unrelated block of code.
The following code is the For-In loop I changed to a for loop. The commented out code was the original code that didn't work and the uncommented for loop is the now working code. This code was used to change font size for text within all instances of a class element:
var release4 = document.getElementsByClassName("release-4");
// for (item in release4){
// release4[item].style.fontSize = "2em";
// };
for (var i = 0 ; i < release4.length ; i++) {
release4[i].style.fontSize = "2em";
}
This is the code I used to activate my template. It is not part of the release-4 class:
var tmpl = document.getElementById('hidden');
document.body.appendChild(tmpl.content.cloneNode(true));
And here is the HTML that goes with it:
<html>
<head>
<title>Manipulate the DOM</title>
</head>
<body>
<div id="release-0">
<p class="release-4"> Here is some text, add a class "done" to the parent div</p>
</div>
<div id="release-1">
<p>remove the #release-1 div</p>
</div>
<h1>Change this text to finish release 2</h1>
<div id="release-3">
<p class="release-4"> add CSS to this div</p>
</div>
<template id="hidden">
<div>
<h1> Congrats! You finished the challenge.</h1>
<img src="http://media.giphy.com/media/2UpzC3iPenf44/giphy.gif">
</div>
</template>
<script type="text/javascript" src="home_page.js"></script>
</body>
</html>
My question is why did changing the For loop make a difference? Thanks everyone!
All other code in the JS file only affect IDs release-0, release-1, and release-3, and the h1 tag. The class name, display, innerHTML, and background color were the only changes made to them.
If I console.log() item in the for in loop it yields:
0
1
length
item
namedItem
I think length, ìtem and namedItem make it error.
Updated:
With Array.from it works as expected.
var release4 = Array.from(document.getElementsByClassName("release-4"));
for (item in release4){
release4[item].style.fontSize = "2em";
};