Monday, May 20, 2024
 Popular · Latest · Hot · Upcoming
159
rated 0 times [  160] [ 1]  / answers: 1 / hits: 17569  / 12 Years ago, wed, july 4, 2012, 12:00:00

I have my CKEDITOR form prepopulated with hidden table which is being submitted together with user inputed text. This works fine, but sometimes user presses backspace too many times and deletes the hidden table.



Is there a way to block editing on this hidden table inside ckeditor textarea? So when user presses backspace the hidden table isn't affected and stays in.



As soon as CKEDITOR instance is ready this source (bellow) is put inside CkEditor Textarea (using setData() attribute) and User only sees the returned <p></p> value. In this case its <p>I really think I can do this!</p>. Its a description of his profile and he can keep it and edit it. The rest is hidden and only visible in e-mail when form is submitted. Its strange that <p></p> is on top but if user presses Backspace couple times the table gets deleted and therefor not submitted.



    <span id=messageTemplate1 class=message>

<p>I really think I can do this!</p>

<table class=hide style=font-size: 12px;>
<tbody>
<tr class=hide>
<td>
Application sent by <strong><a href=http://www.globalcastingcenter.com/talent/jack-bolton>Matt Faro</a></strong> for Audition: <a href=http://www.globalcastingcenter.com:80/CustomContentRetrieve.aspx?ID=4185493>Actors Needed</a>
</td>
</tr>
<tr class=hide>
<td>
Reply to applicant directly: [email protected] or visit full profile: http://www.globalcastingcenter.com/talent/jack-bolton
</td>
</tr>
</tbody>
</table>
<table class=hide style=font-size: 12px;>
<tbody>
<tr class=hide>
<td><strong>Short Profile Summary:</strong></td>
</tr>
</tbody>
</table>
<table class=hide style=font-size: 12px;>
<tbody>
<tr class=hide>
<td>
<a href=http://www.globalcastingcenter.com/talent/jack-bolton><img alt= src=http://globalcastingcenter.com/talent_images/4164035_258551_foto.png?Action=thumbnail&amp;Width=144&amp;Height=215 /></a>
</td>
</tr>
</tbody>
</table>
<table style=font-size: 12px; class=hide>
<tbody>
<tr class=hide>
<td><strong>Areas:</strong></td>
<td>Actor,Extra</td>
</tr>
<tr class=hide>
<td><strong>Country:</strong></td>
<td>WORLDWIDE,Any</td>
</tr>
<tr class=hide>
<td><strong>Age:</strong></td>
<td>26</td>
</tr>
</tbody>
</table>
</span>


Now when I load your plugin my CKeditor box disapears, please press Apply on testing page http://gcc-july.themantas.co.uk/auditions/actors-needed please login first to be able to access the message box Login name: [email protected] pssw: test



My config file:



CKEDITOR.editorConfig = function( config )
{
config.toolbar = 'MyToolbar';

config.toolbar_MyToolbar =
[

{ name: 'clipboard', items : [ 'Undo','Redo' ] },
{ name: 'styles', items : ['FontSize' ] },
{ name: 'basicstyles', items : [ 'Bold','Italic'] },
{ name: 'paragraph', items : ['Outdent','Indent' ] },

];

config.removePlugins = 'contextmenu';
config.forcePasteAsPlainText = true;
config.pasteFromWordRemoveFontStyles = true;
config.pasteFromWordRemoveStyles = true;
config.extraPlugins = 'cwjdsjcsconfineselection';
config.startupShowBorders = false;
config.disableObjectResizing = true;

};


This is how the box looks when I disable your plugin: http://screencast.com/t/Kc2bIOU8md2



I use your suggested HTML structure.


More From » plugins

 Answers
18

I had to play around with it a bit to get it to work. I added lots of documentation to the plugin code, if you have any questions after reading it through let me know.



I'm including an updated version of your content block and the plugin code block.






Here is your updated content block. It wasn't working when wrapped in the <span> tag, so I wrapped it in a table.



You may not like the border and resizing outlines that appear around the data cell, if that's the case, add these settings to your configuration:

config.startupShowBorders = false;

config.disableObjectResizing = true;



Some notes:

The empty <td> before your starting content is needed, it prevents the user from using Ctrl A to select everything which would allow them to delete the hidden table.



I removed the <p> tag from the starting content as it acted funky in this structure.



The <td> that holds the hidden tables has a &nbsp; character, it prevents the user from using Ctrl A to select everything which would allow them to delete the hidden table. It causes the cursor to get lost if you delete everything to the right of the cursor, but you can click on the content to begin editing again.



The contenteditable=false attribute is used by CkEditor and is needed, but it doesn't do the whole job. You can try out the new HTML without activating the plugin to see what effect it has by itself.



There are notes in the plugin code about the classes and ID I used.



<!-- Begin Wrapper Table that Replaces <span> element -->
<table id=messageTemplate1 class=message cwjdsjcs_editable>
<tbody>
<tr>
<td class=cwjdsjcs_not_editable contenteditable=false>
</td>
<td id=cwjdsjcs_editable_id>
I really think I can do this!
</td>
</tr>

<tr class=cwjdsjcs_not_editable contenteditable=false>
<td colspan=2>
&nbsp;

<!-- Begin Original Content -->
<table class=hide style=font-size: 12px; display:none;>
<tbody>
<tr class=hide>
<td>
Application sent by <strong><a href=http://www.globalcastingcenter.com/talent/jack-bolton>Matt Faro</a></strong> for Audition: <a href=http://www.globalcastingcenter.com:80/CustomContentRetrieve.aspx?ID=4185493>Actors Needed</a>
</td>
</tr>
<tr class=hide>
<td>
Reply to applicant directly: [email protected] or visit full profile: http://www.globalcastingcenter.com/talent/jack-bolton
</td>
</tr>
</tbody>
</table>
<table class=hide style=font-size: 12px; display:none;>
<tbody>
<tr class=hide>
<td><strong>Short Profile Summary:</strong></td>
</tr>
</tbody>
</table>
<table class=hide style=font-size: 12px; display:none;>
<tbody>
<tr class=hide>
<td>
<a href=http://www.globalcastingcenter.com/talent/jack-bolton><img alt= src=http://globalcastingcenter.com/talent_images/4164035_258551_foto.png?Action=thumbnail&amp;Width=144&amp;Height=215 /></a>
</td>
</tr>
</tbody>
</table>
<table style=font-size: 12px; display:none; class=hide>
<tbody>
<tr class=hide>
<td><strong>Areas:</strong></td>
<td>Actor,Extra</td>
</tr>
<tr class=hide>
<td><strong>Country:</strong></td>
<td>WORLDWIDE,Any</td>
</tr>
<tr class=hide>
<td><strong>Age:</strong></td>
<td>26</td>
</tr>
</tbody>
</table>
<!-- End Original Content -->

</td>
</tr>
</tbody>
</table>
<!-- End Wrapper Table that Replaces <span> element -->





Here's the plugin code, it's called cwjdsjcsconfineselection.



To add the plugin:

Create a folder called cwjdsjcsconfineselection in the plugins directory: ckeditor/plugins/

Create a file called plugins.js in that directory and paste the code below into that file. My mistake: file is named plugin.js, not plugin(s).js.



If you already have extra plugins, add cwjdsjcsconfineselection to the extraPlugins config setting, otherwise add this setting to your configuration:

config.extraPlugins = 'cwjdsjcsconfineselection';



The plugin should work the next time you load the editor.



For my situation, I have a dialog box appear when the user clicks in a non-editable area to explain why the cursor was moved back to the previous selection. That doesn't seem necessary for your usage, so I commented it out.



/*
Plugin that prevents editing of elements with the non-editable class as well as elements outside of blocks with editable class.
*/

//* ************************** NOTES *************************** NOTES ****************************
/*
The lastSelectedElement variable is used to store the last element selected.

This plugin uses the elementspath plugin which shows all elements in the DOM
parent tree relative to the current selection in the editing area.

When the selection changes, elementsPathUpdate is fired,
we key on this and loop through the elements in the tree checking the classes assigned to each element.

Three outcomes are possible.

1) The non-editable class is found:
Looping stops, the current action is cancelled and the cursor is moved to the previous selection.
The selectionChange hook is fired to set the reverted selection throughout the instance.

2) The editable class is found during looping, the in_editable_area flag is set to true.

3) Neither the editable or the non-editable classes are found (user clicked outside your main container).
The in_editable_area flag remains set to false.

If the in_editable_area flag is false, the current action is cancelled and the cursor is moved to the previous location.
The selectionChange hook is fired to set the reverted selection throughout the instance.

If the in_editable_area flag is true,
the lastSelectedElement is updated to the currently selected element and the plugin returns true.

---------------
If you don't want the elements path to be displayed at the bottom of the editor window,
you can hide it with CSS rather than disabling the elementspath plugin.

The elementspath plugin creates and is left active because we are keying on changes to the path in our plugin.
#cke_path_content
{
visibility: hidden !important;
}

---------------
CSS Classes and ID that the plugin keys on. Use defaults or update variables to use your preferred classes and ID:

var starting_element_id = ID of known editable element that always occurs in the instance.
Don't use elements like <table>, <tr>, <br /> that don't contain HTML text.
Default value = cwjdsjcs_editable_id

var editable_class = class of editable containers.
Should be applied to all top level elements that contain editable elements.
Default = cwjdsjcs_editable

var non_editable_class = class of non-editable elements within editable containers
Apply to elements where all child elements are non-editable.
Default = cwjdsjcs_not_editable

*/

//* ************************** END NOTES *************************** END NOTES ****************************


// Register the plugin with the editor.
// http://docs.cksource.com/ckeditor_api/symbols/CKEDITOR.plugins.html
CKEDITOR.plugins.add( 'cwjdsjcsconfineselection',
{
requires : [ 'elementspath' ],

// The plugin initialization logic goes inside this method.
// http://docs.cksource.com/ckeditor_api/symbols/CKEDITOR.pluginDefinition.html#init
init: function( editor )
{
editor.on( 'instanceReady', function( instance_ready_data )
{
// Create variable that will hold the last allowed selection (for use when a non-editable selection is made)
var lastSelectedElement;
editor.cwjdsjcs_just_updated = false;

// This section starts things off right by selecting a known editable element.
// *** Enter the ID of the element that should have initial focus *** IMPORTANT *** IMPORTANT ***
var starting_element_id = cwjdsjcs_editable_id;

var resInitialRange = new CKEDITOR.dom.range( editor.document );

resInitialRange.selectNodeContents( editor.document.getById( starting_element_id ) );
resInitialRange.collapse();

var selectionObject = new CKEDITOR.dom.selection( editor.document );

editor.document.focus();
selectionObject.selectRanges( [ resInitialRange ] );

var sel = editor.getSelection();
var firstElement = sel.getStartElement();
var currentPath = new CKEDITOR.dom.elementPath( firstElement );

// Set path for known editable element, fire selectionChange hook to update selection throughout instance.
editor._.selectionPreviousPath = currentPath;
editor.fire( 'selectionChange', { selection : sel, path : currentPath, element : firstElement } );
}); // *** END - editor.on( 'instanceReady', function( e )


// When a new element is selected by the user, check if it's ok for them to edit it,
// if not move cursor back to last know editable selection
editor.on( 'elementsPathUpdate', function( resPath )
{
// When we fire the selectionChange hook at the end of this code block, the elementsPathUpdate hook fires.
// No need to check because we just updated the selection, so bypass processing.
if( editor.cwjdsjcs_just_updated == true )
{
editor.cwjdsjcs_just_updated = false;
return true;
}

var elementsList = editor._.elementsPath.list;
var in_editable_area = false;
var non_editable_class = cwjdsjcs_not_editable;
var editable_class = cwjdsjcs_editable;

for(var w=0;w<elementsList.length;w++){
var currentElement = elementsList[w];

// Sometimes a non content element is selected, catch them and return selection to editable area.
if(w == 0)
{
// Could change to switch.
if( currentElement.getName() == tbody )
{
in_editable_area = false;
break;
}

if( currentElement.getName() == tr )
{
in_editable_area = false;
break;
}
}

// If selection is inside a non-editable element, break from loop and reset selection.
if( currentElement.hasClass(non_editable_class) )
{
in_editable_area = false;
break;
}

if( currentElement.hasClass(editable_class) ) {
in_editable_area = true;
}
console.log(currentElement);
console.log(currentElement.getName());
}

// if selection is within an editable element, exit the plugin, otherwise reset selection.
if( in_editable_area ) {
lastSelectedElement = elementsList[0];
return true;
}

var resRange = new CKEDITOR.dom.range( editor.document );

resRange.selectNodeContents( lastSelectedElement );
resRange.collapse();
editor.getSelection().selectRanges( [ resRange ] );
resRange.endContainer.$.scrollIntoView();

// Open dialog window:
// It tells user they selected a non-editable area and cursor has been returned to previous selection
// currentEditorName = editor.name;
// openResDefaultDialog(currentEditorName);

try
{
var sel = editor.getSelection();
var firstElement = sel.getStartElement();
var currentPath = new CKEDITOR.dom.elementPath( firstElement );
editor.cwjdsjcs_just_updated = true;

editor._.selectionPreviousPath = currentPath;
editor.fire( 'selectionChange', { selection : sel, path : currentPath, element : firstElement } );

}
catch (e)
{}
});
} // *** END - init: function( editor )
}); // ************************************************************************************* END - CKEDITOR.plugins.add


To test that the plugin is loaded add an alert after the instance ready trigger:



    editor.on( 'instanceReady', function( instance_ready_data )
{
alert(instanceReady);


To test that the plugin is being triggered when the selection changes, add an alert after the elementsPathUpdate trigger:



    editor.on( 'elementsPathUpdate', function( resPath )
{
alert(elementsPathUpdate);

[#84475] Tuesday, July 3, 2012, 12 Years  [reply] [flag answer]
Only authorized users can answer the question. Please sign in first, or register a free account.
bradford

Total Points: 709
Total Questions: 117
Total Answers: 91

Location: Sao Tome and Principe
Member since Wed, Dec 21, 2022
1 Year ago
;