Added element and child cloning with .neo-dupe - resolves issue #29

This commit is contained in:
Andy Dixon
2024-11-11 19:06:12 +00:00
parent 5f49677bb4
commit af9276de95
2 changed files with 113 additions and 12 deletions
+1 -1
View File
@@ -14,7 +14,7 @@ smoother for your content editing experience.
* No Database Required: NeoCMS works without a database, so you don’t have to worry about setup hassles or performance * No Database Required: NeoCMS works without a database, so you don’t have to worry about setup hassles or performance
slowdowns. slowdowns.
* Easy Content Editing: With our intuitive WYSIWYG editor, anyone can update content without writing a single line of * Easy Content Editing: With our intuitive WYSIWYG editor, anyone can update content without writing a single line of
code. code. Adding the additional class *neo-dupe* will allow an element and it's children to be cloned.
* Seamless Integration: Simply add the CMS to any existing static website. Just assign a special class to the elements * Seamless Integration: Simply add the CMS to any existing static website. Just assign a special class to the elements
you want to make editable, and you’re all set. you want to make editable, and you’re all set.
* Consistent Layouts: NeoCMS supports page templates to keep your layouts neat and uniform across all pages. * Consistent Layouts: NeoCMS supports page templates to keep your layouts neat and uniform across all pages.
+112 -11
View File
@@ -11,9 +11,15 @@ $(document).ready(function () {
// Set up click handler on divs with class 'editable' in the iframe // Set up click handler on divs with class 'editable' in the iframe
$(iframeDoc).find('.editable').css('cursor', 'pointer').click(function (event) { $(iframeDoc).find('.editable').css('cursor', 'pointer').click(function (event) {
editElement(event,$(this));
});
// Edit Element Shared functionality
function editElement(event,element) {
event.preventDefault(); event.preventDefault();
currentDiv = $(this); currentDiv = element;
// Get the content of the div // Get the content of the div
const content = currentDiv.html(); const content = currentDiv.html();
@@ -21,7 +27,7 @@ $(document).ready(function () {
// Set the content in TinyMCE // Set the content in TinyMCE
$('#editor').val(content); $('#editor').val(content);
// Open the modal and init tinyMCE // Open the modal and init TinyMCE
$('#editModal').modal('show') $('#editModal').modal('show')
.on('shown.bs.modal', function () { .on('shown.bs.modal', function () {
tinymce.init({ tinymce.init({
@@ -37,13 +43,65 @@ $(document).ready(function () {
images_upload_credentials: true, images_upload_credentials: true,
force_br_newlines: false, force_br_newlines: false,
force_p_newlines: false, force_p_newlines: false,
forced_root_block: 'aaa',
newline_behavior: 'linebreak' newline_behavior: 'linebreak'
}); });
}); });
}
regenerateButtons();
// Set up event handlers for duplication buttons inside the iframe
$(iframeDoc).on('click', '.duplicate-btn-before', function() {
var parentElement = $(this).closest('.neo-dupe');
var clonedElement = $(parentElement).clone();
// Remove buttons from the cloned element
clonedElement.find('.button-container').remove();
// Add system classes
clonedElement.addClass("neo-dupe");
clonedElement.addClass("editable");
// Insert the cloned element before the original parent element
clonedElement.insertBefore(parentElement);
// Trigger an event on the new duplicated element
clonedElement.trigger('elementDuplicated');
}); });
$(iframeDoc).on('click', '.duplicate-btn-after', function() {
var parentElement = $(this).closest('.neo-dupe');
var clonedElement = $(parentElement).clone();
// Remove buttons from the cloned element
clonedElement.find('.button-container').remove();
// Add system classes
clonedElement.addClass("neo-dupe");
clonedElement.addClass("editable");
// Insert the cloned element after the original parent element
clonedElement.insertAfter(parentElement);
// Trigger an event on the new duplicated element
clonedElement.trigger('elementDuplicated');
});
// Handle the custom 'elementDuplicated' event
$(iframeDoc).on('elementDuplicated', '.neo-dupe', function(event) {
// Example action: Animate the new element
$(this).hide().fadeIn('slow');
// Remove buttons if they are there
$(this).find('.button-container').remove();
editElement(event,$(this));
});
// Here for addButtonsForNeoDupe
}); });
// Save changes made to a div, but not save to the file on the server // Save changes made to a div, but not save to the file on the server
$('#saveBtn').click(function () { $('#saveBtn').click(function () {
// Get the data from TinyMCE // Get the data from TinyMCE
@@ -70,7 +128,11 @@ $(document).ready(function () {
// Handle Saving changes to the page // Handle Saving changes to the page
$('#savePage').click(() => { $('#savePage').click(() => {
frameContainerElement = $('#frameContainer').contents().get(0);
// Remove the buttons container as not to make things awks
$(iframeDoc).find('.button-container').remove();
let frameContainerElement = $('#frameContainer').contents().get(0);
$.post("/cms/controller/", { $.post("/cms/controller/", {
action: "save", action: "save",
uri: frameContainerElement.location.pathname, uri: frameContainerElement.location.pathname,
@@ -81,8 +143,8 @@ $(document).ready(function () {
} else { } else {
showMessage(data.message, "error"); showMessage(data.message, "error");
} }
// alert(data)
}); });
regenerateButtons();
}); });
// Show dialog for page templates // Show dialog for page templates
@@ -139,11 +201,11 @@ $(document).ready(function () {
radioList.empty(); // Clear previous content radioList.empty(); // Clear previous content
data.forEach(function (item, index) { data.forEach(function (item, index) {
radioList.append(` radioList.append(`
<label> <label>
<input type="radio" name="item" value="${item.id}" ${index === 0 ? 'checked' : ''}> <input type="radio" name="item" value="${item.id}" ${index === 0 ? 'checked' : ''}>
${item.name} ${item.name}
</label> </label>
`); `);
}); });
}, },
error: function () { error: function () {
@@ -192,10 +254,48 @@ $(document).ready(function () {
}); });
}); });
// Add buttons to all existing neo-dupe elements inside the iframe
function regenerateButtons() {
$(iframeDoc).find('.neo-dupe').each(function () {
$(this).find('.buttonContainer').remove();
addButtonsToNeoDupe(this);
});
}
// Function to add buttons to a neo-dupe element inside the iframe
function addButtonsToNeoDupe(element) {
/**
* DANGER WILL ROBINSON: This may break stuff, but is needed for the buttons to be positioned properly
* Since this is alpha, lets see how we go.
*/
if ($(element).css('position') === 'static') {
$(element).css('position', 'relative');
}
var $buttonContainer = $(iframeDoc.createElement('div'));
$buttonContainer.addClass('button-container');
$buttonContainer.css("position","absolute");
$buttonContainer.css("top","5px");
$buttonContainer.css("right","5px");
var $duplicateBeforeButton = $(iframeDoc.createElement('button'));
$duplicateBeforeButton.addClass('duplicate-btn-before').text('◀️').prop('title','Clone before');
var $duplicateAfterButton = $(iframeDoc.createElement('button'));
$duplicateAfterButton.addClass('duplicate-btn-after').text('▶️').prop('title','Clone after');
// Append buttons to the container
$buttonContainer.append($duplicateBeforeButton, $duplicateAfterButton);
// Prepend the container to the neo-dupe element
$(element).prepend($buttonContainer);
}
}); });
/** /**
* Show A message bar across the top of the screen for a few seconds * Show a message bar across the top of the screen for a few seconds
* @param message - string - message to be shown * @param message - string - message to be shown
* @param type - string "success" or "error" * @param type - string "success" or "error"
*/ */
@@ -231,4 +331,5 @@ function showMessage(message, type) {
setTimeout(function () { setTimeout(function () {
messageBar.slideUp(); messageBar.slideUp();
}, 5000); }, 5000);
} }