I'm working on a project that uses a basic wysiwyg editor to handle content. The editor is a little to basic to work with custom designs. So my idea was to create some shortcodes to inject html using jquery.
The setup for the html is pretty basic:
<p>[images start]</p>
<img src="some-image.jpg"/>
<div >Content and other tags</div>
<p>[images end]</p>
<p>[images start align="right"]</p>
<img src="some-image1.jpg"/>
<img src="some-image2.jpg"/>
<p>[images end]</p>
<p>[images start align="left"]</p>
<img src="some-image.jpg"/>
<div >Content and other tags</div>
<p>[images end]</p>
The <p>
wraps are made automatically because of the wysiwyg. The "shortcode" is something i made up to start targeting the content with. It's made for the users to have some extra styling options. The current setup works fine when it's not in a loop and there is only one of a kind. But there are more to be targeted and formatted.
// Foreach P that contains 'images start' text
$('p:contains("[images start")').each(function(){
// Get start and end tag
var start = $(this);
var end = $(this).nextAll('p:contains("[images end]")');
// Get content between tags
var content = start.nextUntil(end);
// Create a new div to place content in
start.after('<div ></div>');
// Place content
$('.images-multiple').html(content);
// Just tests to see it target the shortcodes
start.css('color','green');
end.css('color','red');
});
The general idea is to wrap the content between the shortcodes in a div with a class, and delete the shortcodes from the DOM. Preferable with the align value inserted somewhere to target it with css.
Maybe this is not a good approach, but due to limitations I can only insert javascript/jquery, no server side support.
CodePudding user response:
You can use index
in your each
loop to differentiate .images-multiple
elements.
To set text alignment use element.text().includes()
.
// Foreach P that contains 'images start' text
$('p:contains("[images start")').each( function(index) {
const content = $(this).nextUntil($(this).nextAll('p:contains("[images end]")'))
if ($(this).text().includes('align="right"')) {
$(this).before('<div data-index="' index '" style="text-align: right;"></div>');
} else if ($(this).text().includes('align="center"')) {
$(this).before('<div data-index="' index '" style="text-align: center;"></div>');
} else {
$(this).before('<div data-index="' index '" style="text-align: left;"></div>');
}
$(content).appendTo( $('.images-multiple[data-index="' index '"]') )
$(this).next('p:contains("[images end]")').remove()
$(this).remove()
})
.images-multiple {
background-color: yellow;
margin: 10px;
padding: 10px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<p>[images start]</p>
<img src="some-image.jpg"/>
<div >Content and other tags</div>
<p>[images end]</p>
<p>[images start align="right"]</p>
<img src="some-image1.jpg"/>
<img src="some-image2.jpg"/>
<p>[images end]</p>
<p>[images start align="center"]</p>
<img src="some-image.jpg"/>
<div >Content and other tags</div>
<p>[images end]</p>
This will output the following structure: