Remove wrapping p from img in ckeditor - javascript

I'm wanting to remove the p tags that wrap img tags by default in ckeditor.
I don't want to totally disable p tags or change the EnterMode to another tag. I only want to stop images being wrapping in paragraphs.
I want this done client side, not server side.
I have:
<p>Some text in a parapgraph.</p>
<p><img src="picture.jpg"></p>
<p>Another paragraph</p>
I want:
<p>Some text in a parapgraph.</p>
<img src="picture.jpg">
<p>Another paragraph</p>

Quick fix:
This will work if there is nothing else on the line except the three tags.
$str = "<p><img src=\"/file.jpg\" width=\"1\" height=\"2\" /></p>"
$replaced = preg_replace ( "/<p[^>]*?>(<img[^>]+>)<\/p>/" , "$1" , $str )
Updated:
Here is a PHP function. You can call it from JavaScript.
function filter_ptags_on_images($content){
return preg_replace('/<p>\s*(<a .*>)?\s*(<img .* \/>)\s*(<\/a>)?\s*<\/p>/iU', '\1\2\3', $content);
}
add_filter('the_content', 'filter_ptags_on_images');
Reference

jQuery solution to unwrap the img tag at display time. (It won't stop the paras being put in though.)
<script>
$("p img").unwrap();
</script>
It will also unwrap any other images you have on the page, so you'd probably want a tighter selector.

Related

How to get parent element html but not children tags?

I am not sure I gave correct title to my question but I want to ask to do something like:
I want to get HTML content of parent element. By doing this, this will also include HTML tags of children element but I don't want that. I just want children HTML.
For Example:
<div class="test"> This is content of div
<p class="boring_class" style="borinhdlfj"> This is paragraph<br> content.<span><i>As you<br> can</i></span> see I have added <br> tag</p>
</div>
from above example If I use .text() jquery method to get div content I will get text only but not <br> tag. But if I use .html() jquery, this will also include <p class="boring_class" style='dflkdjf'>....</p> but I don't want that.
I just want html of children element which is:This is paragraph<br> content.As you can see I have added <br> tag.
How can I achieve that?
Final output should look like:
This is content of div This is paragraph <br> content.As you can see I have added <br> tag
As one possible interpretation of the question:
Get html of all children, including text [not in a children nodes]
You can use .contents() to include the text nodes of the parent (the parts that aren't in tags, eg "This is content of div") then loop through those to get either text or html depending on where it is, giving:
var output = $(".test").contents().map((i, e) => {
if (e.nodeType == 3)
return $(e).text();
return $(e).html()
})
.toArray()
.join(" ");
console.log(output)
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="test"> This is content of div
<p class="boring_class" style="borinhdlfj"> This is paragraph<br> content.As you can see I have added <br> tag</p>
</div>
Note this includes all whitespace (newlines) which were not included in the question's example output, so you may need to remove these for an exact match.
You can accomplish this in regular javascript by using innerHTML as shown below.
For more info, see: https://developer.mozilla.org/en-US/docs/Web/API/Element/innerHTML
const list = document.getElementsByClassName("test")[0];
const inner = list.innerHTML;
const noP = inner.replace(/<p[^>]*>/g, "").replace(/<\/p[^>]*>/g, "").replace(/\n/g,'');
console.log(noP);
<div class="test"> This is content of div
<p class="boring_class" style="borinhdlfj"> This is paragraph<br> content.As you can see I have added <br> tag</p>
</div>

Get the Text inside the element

<p class="MsoNormal" style="margin-bottom:0cm;margin-bottom:.0001pt;text-align:
justify;line-height:normal">
First Text
<span lang="EN-US" style="font-size:12.0pt;
font-family:"Times New Roman","serif"">
Second Text</span>
</p>
This is my code, how to get the content inside the paragraph tag. [The tag may change to div or ul]. I need all the content inside the paragraph tag by javascript.
The output should be :
First Text Second Text
Sorry I am new to javascript, searched but cant find answer for this relevant problem. Thanks
To get the value of a tag, you can get the element with a selector and use innerHTML to get the value. like this:
<p>hi there</p>
console.log(document.getElementsByTagName('p')[0].innerHTML);
n.b. in the code above it's selecting by tag name, so it returns an array of matching elements
So in your example, using .innerHTML with give you the P tags content, including any html tags etc.
if you want just the content, you can use .textContent
console.log(document.getElementsByTagName('p')[0].textContent);
This wont give you the inner html tags
n.b. there is also the innerText method, However this isnt supported accross browsers.
You can change according to the tag you need, but basically this will do the trick:
document.getElementsByTagName('p')[0].innerText
Fiddle
InnerText should be a good solution.
console.log(document.getElementsByTagName('p')[0].innerText);
<p class="MsoNormal" style="margin-bottom:0cm;margin-bottom:.0001pt;text-align:
justify;line-height:normal">
First Text
<span lang="EN-US" style="font-size:12.0pt;
font-family:"Times New Roman","serif"">
Second Text</span>
</p>

how to find first level of child tag in jquery

I have XML like below
<parent id="parent">
<body>
body text<body>hello</body>
</body>
</parent>
as shown in above code it have parent tag where there is only body tag should available, but there is some text in body tag with tag again.
so if i use
$('#parent').find('body').text();
it show output as
body text hello
but i want the output exactly like
body text<body>hello</body>
how should i do? If again there are more than one body tag are written in first body tag it should be treated as only text. not as tag.
Use html instead:
$('#parent').find('> body').html();
$('#parent').find('body:first').html();
HTML
<body>and another text followed by <div class="someText"></div>Some text followed by</body>
JQuery
var texts = $('.someText, body').map(function(){
return this.previousSibling.nodeValue
});
alert(texts[0]); // "Some text followed by "
alert(texts[1]); // " and another text followed by "
DEMO
You can use some DOM Traversing:
$('#parent').find('body').first().html();

Insert text after an <img> tag

I try to insert text after an <img> tag using javascript.
<div id="candy"><img src="candy.png" /> Insert text here!</div>
If I use document.getElementById('candy').innerHTML = "test"; the image disappears.
Can you help me?
That's because you're replacing the innerHTML with the text test. You're not appending the text.
Try:
var div = document.getElementById('candy');
div.innerHTML = div.innerHTML + 'test';
Taken from here.
Well, the img tag is part of the HTML inside the div, and if you replace the div's HTML you rewrite the img tag as well.
Perhaps you wanted something like this instead:
<div><img src="candy.png" /> <span id="candy">Insert text here!</span></div>
Use
var div = document.getElementById('candy');
div.insertAdjacentHTML('beforeend', 'test');
Reference: https://developer.mozilla.org/en/docs/DOM/element.insertAdjacentHTML
That is because you javascript changes the html inside the <img> tag to test. This doesn't work as <img /> is a self-closing tag.
I believe you could you jQuery to do what you are trying to however.

Jquery remove everything except for bolded

I have html like this:
<div id="divTestArea1">
<b>Bold text</b>
<i>Italic text</i>
<div id="divTestArea2">
<b>Bold text 2</b>
<i>Italic text 2</i>
<div>
<b>Bold text 3</b>
</div>
</div>
and I would like to remove all elements that aren't bold. I've tried with this code:
$('*:not(b)').remove();
and a couple other variations but they all either error out or remove everything. btw, are jquery selectors and jsoup selectors 100% compatible? I'd like to use the answer to this in jsoup as well.
Your current code removes the document <body> as well as all <div>s which contain the <b> tags. If you only want to save the bold text then Shih-En Chou's solution works well. If you want to save the <div> structure that the <b> tags are in as well you could do this:
$("body *:not(div, b)")​​​​.remove();​
DEMO
My solution:
I clone <b> and save it into memory.
->Remove all
-> insert <b> into <body>
here is my code:
http://jsfiddle.net/sechou/43ENq/
$(function(){
var tmpB = $("b").clone();
$('body').remove();
$("body").append(tmpB);
});​
Move all elements in #divTestArea2 as it is a div and will be removed as well to #divTestArea1, then filter out anything that is'nt a <b> and remove it :
$("#divTestArea1").append($("*", "#divTestArea2")).find('*').filter(function() {
return this.tagName !== 'B';
}).remove();
FIDDLE
The above keeps the #divTestArea1 element intact, to remove everything but the <b> elements, something like :
$('body')​.append($('b'))​.find('*')​.not('b')​.remove();​
FIDDLE
I prefer .detach().
var $body = $("body");
var $b = $("b", $body).detach();
$(":not(b)", $body).remove();​​​​​​​​​​​
$body.append($b);
This way you don't need to either move or clone anything to overcome the problem of the deletion of the objects wrapping your <b/> elements.
(demo)
Try this:
// Find all the <b> tags and unwrap them so they all become siblings and finally
// remove non <b> siblings
$('body').find('b').unwrap().siblings('*:not(b)').remove();
Demo: http://jsfiddle.net/3f2Hu/

Categories