jQuery remove() or after() causing whitespace to be removed - javascript

I have the following html:
<p>This is some random text in a paragraph with a <span class="blue">blue</span> word.</p>
<p>This is some random text in a paragraph with a <span class="blue">blue</span> <i>word</i>.</p>
<p>This is some random text in a paragraph with a <span class="blue">blue</span> <span class="blue">word</span>.</p>
My CSS is as follows:
.blue{
color:blue;
}
.popup{
background-color:lightblue;
}
And finally my JS:
var popup = false;
$(".blue").click(function(){
if (!popup){
$(this).after("<div class='popup'>This is some popup text</div>");
popup = true;
}
else{
$(".popup").remove();
popup = false;
}
});
Now my problem, when I call the remove function on my popup class it removes whitespace between tags
As explained in some answers below, the after function could also be causing this.
. eg:
<span class="blue">blue</span> <i>word</i>
becomes
<span class="blue">blue</span><i>word</i>
It does not do this when the text following a blue class is not in tags eg:
<span class="blue">blue</span> word
Why does this happen and how can I prevent it?
For further reference here is a fiddle: http://jsfiddle.net/6fqDq/
Edit: It seems this problem is localized to Chrome as it does not occur in FF or IE.

The reason this is happening is because you added a block element(div), the block element breaks into a new line, then when it's removed, it takes away the whitespace with it that's after it, because for HTML a whitespace and a newline is pretty much the same.
You have several solutions, some were mentioned here :
Use &nbsp
Put a space inside the <i> tag instead of between tags, so <i> word</i> would work fine.
Use a <span> tag instead of a div tag on the after.

I don't think the problem is with remove but with after in this case which probably ignore text node and therefore ignoring the white space. If you use append, also it does place the element somewhere else the problem disappear.
http://jsfiddle.net/6fqDq/8/
var popup = false;
$(".blue").click(function() {
if (!popup) {
$(this).append("<div class='popup'>This is some popup text</div>");
popup = true;
} else{
$(".popup").remove();
popup = false;
}
});

Not sure why it does it. But a quick fix would be to put the white space within the <i> tag. Like this:
<p>This is some random text in a paragraph with a <span class="blue">blue</span><i> word</i>.</p>
See http://jsfiddle.net/6fqDq/5/

just add
<p>This is some random text in a paragraph with a <span class="blue">blue</span> <span class="blue">word</span>.</p>

Use .append instead of .after()
if (!popup){
$(this).append("<div class='popup'>This is some popup text</div>");
popup = true;
}
I can't explain why it doesn't work with .after, but i think it could be appending on the whitespace
DEMO

Not sure why it is happening, but maybe replace your spaces with entities? is a space. You could do it with javascript str.replace('> <', '> <' ) or in php str_replace('> <', '> <', str)

Related

How do I make an element in html not an entire line long

So what I'm trying to make is a paragraph in HTML and then when you click on it it would do a certain action, for example:
<p id='hello'>Hello</p>
<script>
hello.onclick = function() {
console.log("clicked!");
}
</script>
the only problem is that when I click next to the text, it still detects it as a click, I want the click ratio to be the length of the paragraph's text. What's the best way I could do this?
I would suggest you to use inline element instead of p like below -
<span id='hello'>Hello</span>
Because p is block element and no matter where your contents gets over in the line it will takes the space of whole line.
For more in details refer this link
I write an example, I think this helps you
you can see the link
<buttom onclick="clickMe()">click me please</buttom>
<div>
<p id="write"></p>
</div>
<script>
function clickMe() {
let getELementP = document.getElementById("write");
getELementP.innerHTML = "writeHere";
}
</script>

Use innerText to retrieve text from hidden HTML elements

I need to get the text from an html element which is hidden with css. I know that per the specs innerText will abide the css rules. But the alternative of using textContent ignores line break and tabs which I need to keep in the string.
Is there any way around this?
For simplicity please see the following example:
const inntxt = document.querySelector('.expandable').innerText
console.log(inntxt) // Here we don't get the hidden div's text.
const txtct = document.querySelector('.expandable').textContent
console.log(txtct) // Here the result removes the line break.
.hidden{
display: none;
}
<div class='expandable'>
<span class='visib'>
Red balloon
</span>
<br>
<span class='hidden'>
Yellow badge<br>Green ribbon
</span>
</div>
I guess one way around it would be to replace the <br> with my own char like # by appending it instead of the <br>, but there must be a better way no?
UPDATE
To be more clear the end result should be:
For example if you would console.log() the string in node, then the string from our innerText or textContent should be:
'Red balloon\nYellow Badge\nGreen ribbon'
It is very unintuitive that textContent doesn't retrieve <br> new lines.
I suggest using a dummy element in Javascript using innerHTML and replacing all <br> with \n<br>.
Take a look at this code, I think it solves your issue:
const expandable = document.querySelector('.expandable')
const auxEl = document.createElement('div')
auxEl.innerHTML = expandable.innerHTML.replace(/(\<br\>)/, '\n$1')
const textContent = auxEl.textContent
console.log({ textContent })
/* Yields
{
"textContent": "\n \n Red balloon\n \n \n Yellow badge\nGreen ribbon\n \n"
}
*/
.hidden {
display: none;
}
<div class='expandable'>
<div class='visib'>
Red balloon
</div>
<div class='hidden'>
Yellow badge<br>Green ribbon
</div>
</div>
Not sure about what you're trying to achieve here, but what you might want to do is change innerText to innerHTML and then the line breaks are preserved.
Unlike innerText, though, innerHTML lets you work with HTML rich
text and doesn't automatically encode and decode text. In other words,
innerText retrieves and sets the content of the tag as plain text,
whereas innerHTML retrieves and sets the content in HTML format.
Quoted from https://stackoverflow.com/a/19030857/4073621.
Kindly use the following script to get innerText
const inntxt = document.getElementsByClassName('expandable')[0].innerText;
console.log(inntxt);

JQuery highlight not working properly

Reference
I am trying to build a form with the functionality something similar to word search.
I have a text-area and a series of divs with contents. When a user types a word or a sentence, the words that match with the div contents are highlighted in yellow and when text-area content is removed or emptied, highlighting is also removed.
The sample that I made highlights the words but doesn't highlight it completely. Only first character is highlighted. And when I try to search for a new word, previously highlighted words are still highlighted.
HTML
<textarea id="my_ta" name="my_ta"></textarea>
<hr>
Similiar Words
<hr>
<div>
This is a serious question
</div>
<div>
Does this question ring a bell inside your head?
</div>
<div>
This question is a question about questions
</div>
CSS
.highlight { background-color: yellow }
JavaScript
$(document).ready(function(){
$('#my_ta').keypress(function()
{
var value = $(this).val();
if(value)
{
$('div').highlight(value);
}
else
{
$('.highlight').removeHighlight();
}
});
});
FIDDLE
Looking at the documentation, seems that you'de be good to go just with
$(document).ready(function(){
$('#my_ta').on('input',function(){
$('div').removeHighlight().highlight($(this).val());
});
});
Use input or keyup instead of keypress.
http://jsfiddle.net/2vsgbmgz/3/
Rather use Regular Expressions. It's easier to find anything you're looking for.
HTML
<div>
You can have any text inside a <div>
or any valid html tag you want.
</div>
CSS
#highlight {
background-color: red
}
jQuery
function highlight() {
$.each($('div'), function() {
//-------------------------Get Text
var str = $(this).html();
//-------------------------Wrap Matching Text
str = str.replace(/hi/ig, '<span id="highlight">$&</span>');
//-------------------------Insert Coloured Text
$(this).html(str);
});
}
highlight();
jsFiddle

Remove invalid tags with jquery

Im trying to remove some invalid tags/html with jquery, but I think because its invalid the selector cant find it. IE
<p>Here1 is Here is lots of text in page <a href="" class="tooltipster">REMOVE THIS more content</a> and its cool</p>
$("a").find("a").remove();
Nothing happens, however if I change the second a (invalid one) to a span the selector can find and remove it? Thanks
======================================================
Update, ive taken m69s regex and added it to jquery (elements not in DOM so I cant use getelementbyID)
$(.container p).each(function (index) {
var cont = $(this).html().match(/^(.*?<A[^>]+>.*?)<A[^>]+>.*?(<\/A>.*)$/i);
if (cont) $(this).html(cont[1] + cont[2]);
});
This removes the illegal A element, but it doesn't completely restore the legal A element, because the browser removes the second closing A tag. As a result, some text that was inside the link may now come after it. (If you want to avoid the link being empty, you could move the next word into it.)
var elem = document.getElementsByTagName("P");
for (i = 0; i < elem.length; i++) {
var cont = elem[i].innerHTML.match(/^(.*?<A[^>]+>.*?)<A[^>]+>.*?(<\/A>.*)$/i);
if (cont) elem[i].innerHTML = cont[1] + cont[2];
}
<p>A simple text paragraph.</p>
<p>A paragraph with a legal <a href="">ILLEGAL LINK link</a> and some more text.</p>
<p>A paragraph with a legal link and some more text.</p>
Save your file as xhtml, the browser should find the un-closed tags for you. I don't think there is a way that this could be done in javascript.

contenteditable - Selecting 2 child paragraphs and writing text over (Firefox Issue)

I have been searching on Google for over a week now, I've been trying to implement different solutions, but with no success, and it's bugging the hell out of me.
So you have a contenteditable div with several paragraphs(or other child elements of the same kind). Obviously this is the kind of layout you wanna keep. If the user selects two or more paragraphs and types text over it, it removes the paragraphs and sets the caret focus inside the parent div:
body {
font-family: georgia;
}
.editable {
color: red;
}
.editable p {
color: #333;
}
.editable span {
color: limegreen !important;
}
<div class="editable" contenteditable><p>paragraph one</p><p>paragraph two</p></div>
<hr>
<p>How to reproduce the bug:</p>
<ul>
<li>Focus the contenteditable above by placing the cursor somewhere in one of the two paragraphs.</li>
<li>press ctrl-a (in windows or linux) or cmd-a (in osx) to select-all</li>
<li>type some text</li>
<li>red text means that the text went directly inside the contenteditable div, black text means it went inside a paragraph</li>
</ul>
<p>The correct behaviour should be that that select-all and delete (or "type-over") in a contenteditable with only block tags should leave the cursor inside the first block tag.</p>
<p>Webkit gets this right, Firefox gets it wrong.</p>
I did try something like this in Jquery:
$(document).on('blur keyup','div[contenteditable="true"]',function(event){
var sel = window.getSelection();
var activeElement = sel.anchorNode.parentNode;
var tagName = activeElement.tagName.toLowerCase();
if (!(tagName == "p" || tagName == "span")) {
console.log('not on editable area');
event.preventDefault();
//remove window selection
var doselect = window.getSelection();
doselect.removeAllRanges();
}
});
So after blur or keyup event on contenteditable, detect where the caret position and if it's outside accepted editable areas stop the event or something?
I've tried changing the selection range, and a bunch of other stuff but maybe I'm just not seeing it. I'm sure a lot of people have had the same problem, but the only answers I found on Google or here is "content editable sucks", "why don't you just use an open source editor" and that kind of stuff.
Firefox weird behaviour: Inserting BR tags on break line
I have also tried to remove Firefox'es weird behaviour with a function to remove all the <BR> tags firefox automatically inserts. Like this:
function removeBr(txteditor) {
var brs = txteditor.getElementsByTagName("br");
for (var i = 0; i < brs.length; i++) { brs[i].parentNode.removeChild(brs[i]); }
}
So I attached this to a keydown event, and it does exactly what it's expected, however that causes more weird behaviour (like preventing you adding spaces on selected paragraph).
Please vote up the question so we can raise more awareness.
I'm sure a lot of other people have bumped into the same problem, I think it would be good to know if there's a workaround or any "right" way to do it. I think it should really be discussed...
So Firefox injects this abomination - <br></br> - into the contenteditable div when removing the paragraphs.
With a little bit of jQuery we can remove it and replace it with paragraph tags.
Current Limitation - The break tag seems to be injected only when removed with delete or backspace, not when typed over... consider this a concept :-)
Open this example in Firefox to test:
$("button").click(function() {
$("br:not(p br)").replaceWith('<p>Write Me!</p>'); // dont replace when inside p
});
body {
font-family: georgia;
}
.editable {
color: red;
}
.editable p {
color: #333;
}
.editable span {
color: limegreen !important;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div class="editable" contenteditable>
<p>paragraph one</p>
<p>paragraph two</p>
</div>
<hr>
<p>Remove all text to trigger bug in Firefox and hit "fix problem!"</p>
</ul>
<p>Webkit gets this right, Firefox gets it wrong.</p>
<button class="fix">Fix Problem</button>
Whats happening is this, when you select both groups of text and delete them you are also deleting all tags within the editable element. So your actually deleting the <p> tags from the div and then the only thing to write to is the div itself.
Why do you need two seperate paragraph tags? It would be easier to have the div by itself...
Rather than setting the div as editable, have you tried setting the <p> tags as <p contenteditable="true">

Categories

Resources