Customizing Body Color in CKEditor for Dynamic Designs

I am facing an issue with CKEditor that I am hoping to find a solution for. My scenario involves using a jQuery color picker to set the background color of a DIV element, which is then edited by the user in CKEditor. However, I have observed that it is not straightforward to automatically apply the background color of the div element to CKEditor when it loads.

I have explored options like bodyClass and bodyId, but they don't seem to address my specific challenge. Instead of having a class assigned to the element, I have an inline style declaration like

<div class="tp-header" style="background-color:#CCCCCC;">content</div>

My CKEditor invocation looks like this:

var editorId = 'editor1';
var instance = CKEDITOR.instances[editorId];
var color = $('.' + headerElementClass).css('background-color');
if (instance) { CKEDITOR.remove(instance); }
$('#' + editorId).ckeditor({ toolbar: 'BasicHtml', height: '100px', width: '500px', fullPage: false, bodyClass : 'background-color:' + color });
$('#' + editorId).val($('.' + headerElementClass).html());

As you can see, the attempt to use bodyClass has not been successful. Is there any other method to achieve this? I have searched extensively for solutions online but haven't come across one yet. Hopefully, someone here can provide some insights.

Answer №1

After some consideration, I have devised a simpler solution.
Since I am not using the CKEditor jQuery adapter, you may need to make adjustments based on your specific requirements.

I conducted tests using the standard JavaScript integration method.

Here is a brief summary:
Set the necessary variables.
Instantiate the editor.

Add this "addCss" function call:

CKEDITOR.instances[editorId].addCss( 'body { background-color: '+color+'; }' );

That's essentially all there is to it. Below is a sample implementation tailored to your code:

// Include the "id" attribute:
<div id="editor1" class="tp-header" style="background-color:#CCCCCC;">content</div>

// Define the variables, including "headerElementClass".
var headerElementClass = "tp-header";
var color = $('.' + headerElementClass).css('background-color');
var editorId = 'editor1';

// Initialize the instance.
var instanceOne = CKEDITOR.replace( editorId,
{
  toolbar: 'Basic',
  height: '100px',
  width: '500px',
  fullPage: false,
  customConfig : 'yourCustomConfigFileIfUsed.js'
 });

// Add the "addCss" function call:
instanceOne.addCss( 'body { background-color: '+color+'; }' );


If preferred, the addCss function call can be moved to your configuration file (place it outside the editorConfig function).

Best regards, Joe


Instead of opting for a more complex approach, others might find these concepts beneficial.

You could utilize ( bodyClass: 'nameOfClass' ) and assign a value to the background-color property of that class. However, this becomes challenging with a dynamic background color.

To dynamically assign the background color, consider the following extension of your existing code using jQuery:

var editorId = 'editor1';
var instance = CKEDITOR.instances[editorId];
var color = $('.' + headerElementClass).css('background-color');

// Create a unique body id for this instance "editor1" ( bodyIdForEditor1 )
var idForBody = 'bodyIdFor' + editorId;

if (instance) { CKEDITOR.remove(instance); }

// Use bodyId instead of the original bodyClass assignment
$('#' + editorId).ckeditor({ 
  toolbar: 'BasicHtml', 
  height: '100px', 
  width: '500px', 
  fullPage: false, 
  bodyId : idForBody 
});

$('#' + editorId).val($('.' + headerElementClass).html());

// Set the background color to the body after both document and editor instance are ready

// Trigger the document ready event
$(document).ready(function(){

  // Wait for the instanceReady event to fire for this (editor1) instance
  CKEDITOR.instances.editor1.on( 'instanceReady', 
    function( instanceReadyEventObj )
    {
      var currentEditorInstance = instanceReadyEventObj.editor;
      var iframeDoc=null;

      // Utility function to streamline repetitive steps
      function setIframeBackground()
      {
        $("#cke_contents_editor1 iframe").attr("id", "cke_contents_iframe_editor1");
        $('#cke_iframe_editor1').each( 
          function(){ iframeDoc=this.contentWindow.document;}
        );

        $('#' + idForBody, iframeDoc).css("background-color", color);
      }

      // Call the function upon initial loading of the editor instance
      setIframeBackground();

      // Reapply the color when switching back from "source" view mode which destroys the iframe
      currentEditorInstance.on( 'mode', function()
      {
        if(currentEditorInstance.mode == 'wysiwyg')
          setIframeBackground();
      });
    }
  );
});

Best regards, Joe

Answer №2

An excellent suggestion from codewaggle is to apply inline styles directly to the editor's <body> element using:

editor.document.getBody().setStyle()

Alternatively, you can use:

editor.document.getBody().setStyles()

Keep in mind that you will need to reapply these styles every time after calling editor.setData() and switching between wysiwyg and source modes, as these actions recreate the editor iframe. To streamline this process, create a function like setEditorStyle, ensuring that editor.mode==='wysiwyg' before applying any styles (as editor.document would be null otherwise). Then, attach this function as an event listener for the instanceReady and mode events, and perhaps also the contentDom event if you call setData() without manually triggering it afterwards.

For more insights, refer to other relevant answers on StackOverflow here and here

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Solution: The issue where the children's onChange event was not updating the parent in Ant Design was discovered to be due to the Select and Table components nested inside a Tab not changing according to the pageSize

I'm facing an issue with updating a parent element when the children's onChange event is triggered. Specifically, I have an Ant Design Select and Table inside a Tab that are not reflecting changes in the pageSize value. Although setPageSize func ...

Can the same form be submitted with two different actions?

I am facing an issue with a form that is supposed to submit data to 2 different pages using the POST method. After trying some javascript code, I found that one form submission works correctly while the other does not. <form id="add"> <input ...

ng-repeat not functioning properly when using track by, filter, and orderBy

I have come across this code snippet. http://jsfiddle.net/0tgL7u6e/ Scripting in JavaScript var myApp = angular.module('myApp',[]); function MyCtrl($scope) { $scope.nameFilter = ''; $scope.contacts = [ {name: 'G ...

A guide on encrypting the data of a file that is uploaded in Meteor.js

As a newcomer to Meteor and coding in general, I have completed tutorial projects and examples and now feel ready to start my own project. I want users to be able to select a file from their computer using an input field, read the contents of the file, and ...

Troubleshooting Bootstrap select box design discrepancies

Currently revamping a website and encountered an unusual issue with select boxes. There seems to be an overlapping white space where the option values should be. Here's a visual reference: View Image of Select Box Issue Utilizing Bootstrap for the re ...

Improve the functionality of select[multiple] to allow for single-click modifications without the need for CMD/CTRL

I am attempting to modify the default functionality of a select element so that clicking once on its options changes their selected state. Essentially, I want to eliminate the confusing requirement of holding down shift/ctrl to select multiple options. I ...

Creating an interactive map on WordPress: A step-by-step guide

I have successfully created a clickable image on Codepen <div style="width: 1000px; height: 993.73px;"> <img src="https://www.dyfedarchaeology.org.uk/wp/wp-content/uploads/Testmap.svg" alt=&q ...

Changing the designated materialUI class

Within the project, I am utilizing this theme: export const theme = createMuiTheme({ ...defaultThemeConfig, overrides: { ...defaultThemeConfig.overrides, MuiListItem: { root: { '&:nth-child(odd)': { backgro ...

Encountering problems when transforming Next.js server components into client components

I've been working on a blog site using next.js. Initially, I had a home page that was a server component, but I wanted to convert it into a client component to add interactivity like pagination. However, after converting the code to a client componen ...

Issue with Ajax not triggering PHP script

My first experience with using Ajax to call a php script is not going well. The script doesn't seem to be working at all. Here is the snippet of code where I implemented Ajax: <?php if (isset($_GET['error'])) { switch ($_GET[ ...

Buffering ceases on the video

I am experiencing an issue with 4 videos and a preloader, which should hide once all the videos are fully buffered. <div id="preload"> <h1> Download... </h1> </div> <video preload="auto" class= ...

Discover all related matching documents within a string array

I am using a mongoose schema model with a field called tags which is an array of strings to store tags for each document. I need functionality where if I search for a specific tag, such as "test," it will return all documents with tags like "testimonials" ...

Developing Authorization in AngularJS

Incorporating authorization into an AngularJS project is crucial. In my current project, which revolves around a social media concept, users with different roles may have varied access to view files. For instance, envision two distinct roles: customer and ...

using jquery, how can you send multiple parameters in an ajax request

Hello and welcome! I'm having trouble passing parameters through an ajax URL. I am attempting to send multiple data using the jQuery $.ajax method to my PHP script, but I can only pass a single data item when concatenating multiple data entries toget ...

Defeat a JavaScript function or turn it into a Singleton Function

Is there a method to stop a running JavaScript function? Or is there a way to make sure that only one instance of the function runs at a time and any previous instances are removed upon restart? For example, if I call: _.defer(heavyDutyPaint); //How ca ...

Tips on implementing a datepicker inside an update panel

I've been attempting to implement a datepicker within an updatepanel, but it doesn't seem to be working for me. After consulting Stack Overflow and finding similar questions with their respective answers, I tried implementing those solutions to ...

When using React, draggable components with input fields may lose their ability to receive focus when clicking on the input field

<Draggable axis="y" grid={[135,135]} onStop={this.handleStop} defaultPosition={{x: this.props.task.positionX, y: this.props.task.positionY,}}> <div id="edit-task-component"> <form onSubmit={this.handleSubmit} id=" ...

Tips for accessing the next sequential tag that is similar in HTML with the help of jQuery

I have generated the following HTML code from some plugins. <div class="parent"> <span>item1</span> <input type="hidden"></input> <span>item2</span> <span class="active">item3</span> <inpu ...

Enhance the performance of node.js when processing data from a massive file

My dilemma lies in the challenge of reading and processing a large file with numerous rows. When dealing with small files under 50kb, everything runs smoothly. However, I am faced with a 15MB file for a programming competition, which serves as a hard input ...

What is the best way to transfer information to a different component using Vue router?

At the moment, I have a component that is displayed on the page. When I check the this.$router variable inside this component, I notice that the full path property is '/hello/reports?report=3849534583957' and the path property is '/hello/rep ...