17

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.

Morne
  • 1,623
  • 2
  • 18
  • 33
  • 4
    Why the whitespace is so important to you? – fracz Jun 10 '14 at 14:02
  • 12
    @WojciechFrącz Because "some thing" and "something" are not equivalent. – Etheryte Jun 10 '14 at 14:03
  • Add space in your CSS using padding – Mateusz Nowak Jun 10 '14 at 14:05
  • 1
    The white space is important as I have a red class as well and sometimes a red word and a blue word comes next to each other. They should have the space or else it becomes one word. – Morne Jun 10 '14 at 14:05
  • Although it has been suggested that I just add   it seems like a quick fix which I would rather not want to do. It feels safer to rather fix my JS – Morne Jun 10 '14 at 14:22
  • 1
    I'm pretty sure this isn't a jQuery problem. If you look in Dev Tools, the DOM doesn't change around the `.popup` before and after the `.remove()` call; it almost looks like the space is never there. `.append()` "works" because it's doing something totally different - it doesn't affect the surrounding DOM – Ian Jun 10 '14 at 14:24
  • 2
    I see the question was voted to be closed as off-topic, due to "a problem that can no longer be reproduced or a simple typographical error". I do not think this is the case as it can be reproduced easily and it is definitely not a typo that caused the problem – Morne Jun 10 '14 at 14:39
  • Should a bug report be filed for Chrome? – Kevin Jun 10 '14 at 18:11
  • 1
    I have started checking the bugs for chromium, didnt find something similar yet. If I havent found one by the end of the day I will file a bug report. – Morne Jun 11 '14 at 06:04

6 Answers6

7

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 :

  1. Use &nbsp
  2. Put a space inside the <i> tag instead of between tags, so <i> word</i> would work fine.
  3. Use a <span> tag instead of a div tag on the after.
Ja͢ck
  • 170,779
  • 38
  • 263
  • 309
Patrick
  • 3,289
  • 2
  • 18
  • 31
  • 1
    Something to note: http://stackoverflow.com/questions/8397852/why-p-tag-cant-contain-div-tag-inside-it – Ian Jun 10 '14 at 14:26
  • But is a

    not also a block element? Why does it not happen with that then?

    – Morne Jun 10 '14 at 14:28
  • @Morne Look what happens when the popup is a ``: http://jsfiddle.net/4EdE2/ - it works fine – Ian Jun 10 '14 at 14:29
  • @Morne Actually it's not invalid, it kinda proves it's not a problem with the JavaScript/jQuery, but with the HTML – Ian Jun 10 '14 at 14:33
  • 3
    I see this actually only happens in Chrome. FF and IE does not cause this problem, so now it shifted from a jquery to html to browser problem – Morne Jun 10 '14 at 14:42
  • @Morne Interesting find, I was wondering if it was only Chrome – Ian Jun 10 '14 at 14:45
  • 1
    @Morne It's just weird, in Dev Tools I don't explicitly see the space in between, for the second and third examples. But I see it for the first example – Ian Jun 10 '14 at 14:46
  • Trying to shed some more light on the matter, I reconstructed the .after using native JS : http://jsfiddle.net/6fqDq/17/ - same effect. @Ian note that the space is indeed there, Try editing the parent node as HTML in chrome dev tools, (the parent P), you'll see all the spaces there, they just won't show :) – Patrick Jun 10 '14 at 14:52
  • @Patrick Right, I guess what I meant is in the DOM inspector, I don't see it. The elements are just on separate lines. But you're definitely right, editing the parent shows the space – Ian Jun 10 '14 at 14:57
6

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;
    }
});
GillesC
  • 10,647
  • 3
  • 40
  • 55
  • 1
    Append does work, I think this is the best solution so far. It requires no 'fixes'. – Morne Jun 10 '14 at 14:15
  • 2
    It requires no fixes, but also doesn't do the same thing; it creates the popup inside the `.blue` element instead of after it. – Ja͢ck Jun 10 '14 at 14:24
  • Make sure you wont use whitespaces in the blue element. Else you might run into the same issue again!!! – PcPulsar Jun 10 '14 at 14:26
1

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/

AndrewPolland
  • 3,041
  • 4
  • 28
  • 39
  • 1
    I will upvote your answer as it does solve the problem, but I will let the question stay unanswered a bit longer to see if I cant find the explanation behind this. Thank you. – Morne Jun 10 '14 at 14:07
  • 1
    While this may work for merely handling a missing white-space, the solution is fragile, for example, imagine if the tag is styled with a background. It's a solution, but not a good one. – Etheryte Jun 10 '14 at 14:08
  • Thanks. Sounds like a plan. :) – AndrewPolland Jun 10 '14 at 14:08
  • @Nit Agree, but if it works for scenario and if it's an oddity with the remove() function, then I'd say it's a good way to go without making the code more complicated. – AndrewPolland Jun 10 '14 at 14:10
  • From seeing other answers now, it does seem to be more to do with the after() rather than the remove(). So I'd recommend taking the approach of changing to using append() instead of after(). – AndrewPolland Jun 10 '14 at 14:13
  • I agree, I think I will edit the question to include both as possible causes. – Morne Jun 10 '14 at 14:16
1

just add &nbsp;

<p>This is some random text in a paragraph with a <span class="blue">blue</span>&nbsp;<span class="blue">word</span>.</p>
Anees Hikmat Abu Hmiad
  • 3,460
  • 2
  • 19
  • 36
0

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

Anton
  • 32,245
  • 5
  • 44
  • 54
  • 3
    Append is a completely different solution as it appends the string inside the blue div in stead after the blue div element. – PcPulsar Jun 10 '14 at 14:15
  • I agree but for my specific case it will not have an effect on the outcome. So it solves my problem, but not the larger problem. – Morne Jun 10 '14 at 14:19
-1

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

RaneWrites
  • 268
  • 1
  • 2
  • 12