Changing html of <p> without changing <span> - javascript

I have a span inside a paragraph and want to be able to change the paragraph text and the span text from button clicks. Right now when I call the function the paragraph is updated but the span disappears.
<p id = "a">Some text to change <span id = "b" onmouseenter="test()">click!</span></p>
function test() {
$("#a").html("New text here");
$("#b").html("click again!");
}

If you change the HTML of the parent p, it will remove everything inside it. However, you can restructure your html to have two spans inside the p and update the text of those.
Here's an example with #c as the first span and #b as the second:
function test() {
$("#c").text("New text here ");
$("#b").text("click again!");
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<p id = "a"><span id = "c">Some text to change </span><span id = "b" onmouseenter="test()">click!</span></p>

Related

javascript, on click change the html of an element different than the one that was clicked on

I am trying to change the innerhtml of a p tag by clicking on a word, but I do not want to change the innerhtml of the word that I clicked on. I want to change the word that is displayed next to the word that I clicked on.
my html looks like this. each id of the word clicked on is followed by a black p tag with an id that is one more than the one that was clicked on
<p id="word0" data-index=0 class="russian"> люблю</p>
<p id="word1" data-index=1 class="english"></p>
the black p tag for the english word should be filled in by the english word when i click on the russian word.
here is my javascript. for the time being the words one two three ect, will be placed next to the russian word when it is clicked. is there a way that i can target the innerHTML of the tag next to the word that is clicked on?
<script>
let allWordsList = {'word0':'one','word1':'one','word2':'two','word3':'three'}
function changeText(e){
var number = e.target.id;
// Set the text to the data-index value of the HTML element:
e.target.innerHTML = allWordsList[number];
}
</script>
You are changing the innerHTML of the clicked element. e is the event for the para on which you clicked and e.target is the HTML element on which you clicked. So if you change the innerHTML of e.target then it would change its own not its next sibling.
e.target.innerHTML = allWordsList[number];
one way to solve this is:
let allWordsList = {
'word0': 'one',
'word1': 'one',
'word2': 'two',
'word3': 'three'
}
function changeText(e) {
var number = e.target.id;
var convertedNumber = allWordsList[ number ];
//Set the text to the data-index value of the HTML element:
const nextSibling = e.target.nextElementSibling;
nextSibling.innerHTML = convertedNumber;
}
const paragraphs = document.querySelectorAll(".para");
paragraphs.forEach( e => {
e.addEventListener("click", changeText);
})
<p id="word0" data-index=0 class="russian para"> люблю</p>
<p id="word1" data-index=1 class="english"></p>
<p id="word2" data-index=0 class="russian para"> люблю</p>
<p id="word3" data-index=1 class="english"></p>

Insert HTML tag to multiple selected text from different paragraph tags in html

I am trying to add new HTML tags for the multi selected text from the different paragraph tag. HTML code snippet as below:
<div class="sampleContent">
<p>Hello</p>
<p>This one is</p>
<p>Sample Text</p>
</div>
So in above snippet I have selected "llo" text from first P tag, "This one is" text from second P tag and "Sample" text from third P tag. Now on any button selection that newly created tag should get added to all selected text so that output will be like below:
<div class="sampleContent">
<p>"He"<div id="1"> llo </div></p>
<p><div id="1"> This one is </div></p>
<p><div id="1"> Sample </div>Text</p>
</div>
So How can I add this newly created "div" element for all the selected text?
I Tried below code:
const wrapper = document.getElementsByClassName('sampleContent')[0];
wrapper.addEventListener('mouseout', event => {
const selection = window.getSelection();
if (selection.rangeCount) {
const replacement = document.createElement('div');
replacement .setAttribute( "id", "1" );
replacement.textContent = selection.toString();
const range = selection.getRangeAt(0);
range.deleteContents();
range.insertNode(replacement);
}
});
But it is giving output as :
<div class="sampleContent">
<p>"He"<div id="1"> llo
This one is
Sample
</div></p>
<p>Text</p>
</div>
This will solve your problem.
var count=0;
const wrapper = document.getElementsByClassName('sampleContent')[0];
wrapper.addEventListener('mouseup', event => {
count++;
const original=event.target.textContent.toString();
const selection = window.getSelection();
if (selection.rangeCount) {
const replacement = document.createElement('div');
replacement .setAttribute( "id", count );
replacement.textContent = selection.toString();
const range = selection.getRangeAt(0);
var array=original.split("");
array.splice(range.startOffset,range.endOffset-range.startOffset)
var string=array.join("");
event.target.textContent=string;
range.deleteContents();
range.insertNode(replacement);
}
});
Basically what I did is
Changed the event from mouseout to mouseup for more accurate results.
I applied a counter which increments on every selection event. This counter will be your id for the div. Same id of multiple elements should not be present, because of that all your results were clubbed into one div.
I took the whole paragraph text in a variable and removed the selected part from it and appended it back to the paragraph with the div.
Results-

Select div with a text inside in JS

I want to modify a div with a special text inside like this.
<div>
<p>
A global issue
</p>
</div>
How can I get it in JS without using id or class ? And only the div with the text "A global issue".
Is there a way to do it?
To target the div and set it to display: none you can run either:
// Pure JS
document.querySelector("div p").style.display = "none"
// w/jQuery
$('div p').hide();
If there's more then one div p tags in your HTML, you can also search by text using the following:
$('div p:contains("A global issue")').css('display', 'none');
If you want to use simple javascript solution, see snippet below
First, get all divs from page
Second, store your search text in a variable
Third, loop through all divs and find the one containing your text, then you can do whatever you want with it. I added a backgroundColor red to it
var divs = document.querySelectorAll("div");
var myText = "A global issue";
var i;
for (i = 0; i < divs.length; i++) {
if (divs[i].textContent.indexOf(myText) > 0 ) {
divs[i].style.backgroundColor = "red";
}
}
<div>
<p>
A global issue
</p>
<p>
More text here
</p>
</div>
<div>
<p>
Not a good text
</p>
</div>
You can use jquery:
$('div:contains("A global issue")').css('background-color', 'red');
<div>A global issue</div>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
let i=5;
let divs =Array.from( document.querySelectorAll('div > p')); // it returns array
divs[i].style.display= "none";
Edit:
for(let i=0;i<divs.length;i++){ if(divs[i].textContent==="some text"){ divs[i].style.display="none"; } }
if you want to change parent node do divs[i].parentNode.style.display="none"

Getting the parent element with display block

I have this html
<div id="editor" contenteditable="true">
This text is directly under div
<p>Some text under p tag. <span> Some under span tag</span> and this is another text</p>
<p>Another para</p>
</div>
<button>Get block level parent</button>
Javascript
function getParentBlock() {
element = document.getSelection().focusNode;
while (p = element.parentNode) {
displaystyle = window.getComputedStyle(p, null).getPropertyValue('display');
if (displaystyle == 'block') {
return p;
}
element = element.parentNode;
}
}
function alertCurrentParent() {
alert(getParentBlock());
}
btn = document.querySelector('button');
btn.onclick = alertCurrentParent;
The jsfiddle is here: http://jsfiddle.net/shankardevy/aA8Kb/
Now when I place the cursor inside the text 'Another Para' or doubleclick the 'Another Para' (which in my mac selects the whole para) and click the button 'Get block level parent', I get HTMLParagraphElement in alert.
However, when I place the cursor in first para ("Some text under p tag"), and I click the button, I get "HTMLParagraphElement" in alert. And when I double click the second para which selects the entire first paragraph, and click the button, I get "HTMLDivElement".
I want my code to work as in the second paragraph. i.e., double click the sentence and click the button, it should show me "HTMLParagraphElement". How do I do that?
Any help is much appreciated!
The problem is that you start your loop with the parent node. When you select the entire paragraph, its parent is the DIV. So start your loop at the current element instead of the parent.
function getParentBlock() {
var element = document.getSelection().focusNode;
for (var p = element; p; p = p.parentNode) {
var style = window.getComputedStyle(p, null);
if (style) {
var displaystyle = style.getPropertyValue('display');
if (displaystyle == 'block') {
return p;
}
}
}
}
FIDDLE
You have to test the result of getComputedStyle before calling getPropertyValue, because text nodes don't have a style and it returns null.

Onclick event on a paragraph is triggered under the paragraph

I wich to replace a paragraph with a textarea tag when clicking on the paragraph, the textarea should contain the text that was in the paragraph:
<div id="right"><p><pre><?php echo $descri; ?></pre></p></div>
Jquery script :
$(function(){
$('#right').on('click', 'p', function(){
var $p = $(this);
var old = $p.html();
if(/<textarea rows="4" cols="40" id="descri" name="descri"/.test(old))
return;
$p.html('<textarea rows="4" cols="40" id="descri" name="descri" value="' + old + '"/>')
.find('textarea')
.focus()
.on('blur', function(){
var value = this.value;
$.post('listener_updates.php', {description: value})
.done(function(){
$p.html(value);
})
.fail(function(){
$p.html(old);
alert('Could not update title');
});
});
});
});
Now when I click on the paragraph text, nothing happens but when I click a little under the paragraph text, then the textarea appears and is empty.
Thank you for your help
This is because you can't put a pre element inside a p element, so the browser's correcting the invalid DOM. The content model of p is phrasing content, but pre isn't valid in phrasing content, only flow content.
When you give this to Chrome:
<div class="right"><p><pre>This is the text</pre></p></div>
...it actually creates this DOM:
<div class"right"><p></p><pre>This is the text</pre><p></p></div>
Note that the pre is no longer in any p.
If you want the pre, simply use pre on its own (without the p). pre is a lot like like p: They both have the same content model, they're both valid in the same places, and they're both display: block by default.
Alternately, if your only goal is not to have line wrapping and other such, on modern browsers you can get rid of the pre (keeping the p or using a div if the semantics of p aren't appropriate) and use the CSS white-space property (e.g., white-space: pre) instead.
Re your comment below:
but I can't get the text inside the pre tag to show on the textarea
Just put the pre's contents() into the textarea, put the textarea in the DOM where you want it, and remove or hide the pre. This removes it, for instance: Live Example
$(".right").on("click", "pre", function() {
var $pre = $(this);
var $textarea = $("<textarea>");
$textarea.append($pre.contents());
$pre.replaceWith($textarea);
return false;
});

Categories

Resources