Commit 6e53cb2c authored by Romain Courteaud's avatar Romain Courteaud

[erp5_xhtml_style] Add ckeditor gadget

Make ckeditor responsive.
Disable ACF.
parent 5e0322ed
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="File" module="OFS.Image"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_Cacheable__manager_id</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>__name__</string> </key>
<value> <string>ckeditor.gadget.appcache</string> </value>
</item>
<item>
<key> <string>content_type</string> </key>
<value> <string>text/cache-manifest</string> </value>
</item>
<item>
<key> <string>precondition</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string></string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
<!DOCTYPE html>
<html manifest="ckeditor.gadget.appcache">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>CKEditor Gadget</title>
<script src="rsvp.js" type="text/javascript"></script>
<script src="renderjs.js" type="text/javascript"></script>
<!-- This gadget provides ckeditor with all Plugins activated by default -->
<!-- Make sure to check the timestamp of your CKEditor version in order to update the manifest -->
<script src="ckeditor/ckeditor.js"></script>
<script src="ckeditor.gadget.js" type="text/javascript"></script>
</head>
<body>
<div class="ckeditor_gadget"><textarea></textarea></div>
</body>
</html>
\ No newline at end of file
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="File" module="OFS.Image"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_Cacheable__manager_id</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>__name__</string> </key>
<value> <string>ckeditor.gadget.html</string> </value>
</item>
<item>
<key> <string>content_type</string> </key>
<value> <string>text/html</string> </value>
</item>
<item>
<key> <string>precondition</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string></string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
/*global window, document, rJS, CKEDITOR, RSVP*/
/*jslint nomen: true, maxlen:80, indent:2*/
(function (window, document, rJS, CKEDITOR, RSVP) {
"use strict";
// erp5_globals is not in xhtml_style.
// Copy/Paste this function for now
function loopEventListener(target, type, useCapture, callback,
prevent_default) {
//////////////////////////
// Infinite event listener (promise is never resolved)
// eventListener is removed when promise is cancelled/rejected
//////////////////////////
var handle_event_callback,
callback_promise;
if (prevent_default === undefined) {
prevent_default = true;
}
function cancelResolver() {
if ((callback_promise !== undefined) &&
(typeof callback_promise.cancel === "function")) {
callback_promise.cancel();
}
}
function canceller() {
if (handle_event_callback !== undefined) {
target.removeEventListener(type, handle_event_callback, useCapture);
}
cancelResolver();
}
function itsANonResolvableTrap(resolve, reject) {
var result;
handle_event_callback = function (evt) {
if (prevent_default) {
evt.stopPropagation();
evt.preventDefault();
}
cancelResolver();
try {
result = callback(evt);
} catch (e) {
result = RSVP.reject(e);
}
callback_promise = result;
new RSVP.Queue()
.push(function () {
return result;
})
.push(undefined, function (error) {
if (!(error instanceof RSVP.CancellationError)) {
canceller();
reject(error);
}
});
};
target.addEventListener(type, handle_event_callback, useCapture);
}
return new RSVP.Promise(itsANonResolvableTrap, canceller);
}
// http://nightly.ckeditor.com/17-10-11-06-04/full/samples/toolbarconfigurator/index.html#advanced
var TOOLBAR_MOBILE = [
{name: 'basicstyles', items: ['Bold', 'Italic', 'Underline']},
{name: 'paragraph', items: ['NumberedList', 'BulletedList']},
{name: 'links', items: ['Link']},
{name: 'insert', items: ['Image']},
{name: 'styles', items: ['Format']}
],
TOOLBAR_DESKTOP = [
{name: 'document',
items: ['Source', '-', 'Save', 'Print', '-', 'Templates']},
{name: 'clipboard', items: ['Undo', 'Redo']},
{name: 'editing', items: ['Find', 'Replace', '-', 'SelectAll',
'-', 'Scayt']},
'/',
{name: 'basicstyles',
items: ['Bold', 'Italic', 'Underline', 'Strike', 'Subscript',
'Superscript', '-', 'RemoveFormat']},
{name: 'paragraph',
items: ['NumberedList', 'BulletedList', '-', 'Outdent',
'Indent', '-', 'Blockquote', 'CreateDiv', '-',
'JustifyLeft', 'JustifyCenter', 'JustifyRight',
'JustifyBlock', '-', 'BidiLtr', 'BidiRtl', 'Language']},
{name: 'links', items: ['Link', 'Unlink', 'Anchor']},
{name: 'insert',
items: ['Image', 'Table', 'HorizontalRule', 'Smiley',
'SpecialChar', 'PageBreak']},
'/',
{name: 'styles', items: ['Styles', 'Format', 'Font', 'FontSize']},
{name: 'colors', items: ['TextColor', 'BGColor']},
{name: 'tools', items: ['ShowBlocks']}
],
MOBILE_CONFIGURATION = {
toolbar: TOOLBAR_MOBILE,
disableNativeSpellChecker: false,
// Disable ACF to not destroy HTML on mobile
allowedContent: true
},
DESKTOP_CONFIGURATION = {
toolbar: TOOLBAR_DESKTOP,
disableNativeSpellChecker: false,
// Disable ACF to not destroy HTML on mobile
allowedContent: true
},
MATCH_MEDIA = window.matchMedia("not screen and (min-width: 45em)");
rJS(window)
.declareAcquiredMethod("notifySubmit", "notifySubmit")
.declareJob("deferNotifySubmit", function () {
// Ensure error will be correctly handled
return this.notifySubmit();
})
.declareAcquiredMethod("notifyChange", "notifyChange")
.declareJob("deferNotifyChange", function () {
// Ensure error will be correctly handled
return this.notifyChange();
})
.setState({
is_mobile: false
})
.declareMethod('render', function (options) {
return this.changeState({
key: options.key,
value: options.value || "",
editable: options.editable === undefined ? true : options.editable,
configuration: options.configuration || DESKTOP_CONFIGURATION,
configuration_mobile: options.configuration_mobile ||
MOBILE_CONFIGURATION,
is_responsive: (options.configuration_mobile !== undefined) ||
(options.configuration === undefined)
});
})
.declareMethod('getContent', function () {
var result = {};
if (this.state.editable) {
result[this.state.key] = this.ckeditor.getData();
}
return result;
})
.onStateChange(function (modification_dict) {
var gadget = this,
configuration;
if (modification_dict.hasOwnProperty('configuration') ||
modification_dict.hasOwnProperty('configuration_mobile') ||
modification_dict.hasOwnProperty('is_responsive') ||
modification_dict.hasOwnProperty('is_mobile')) {
// Expected configuration changed.
// Recreate ckeditor
if (gadget.hasOwnProperty('ckeditor')) {
// Destroy previous instance
gadget.ckeditor.destroy();
}
// Create a new editor
if (gadget.state.is_responsive && gadget.state.is_mobile) {
configuration = gadget.state.configuration_mobile;
} else {
configuration = gadget.state.configuration;
}
gadget.ckeditor = CKEDITOR.replace(
this.element.querySelector('textarea'),
configuration
);
gadget.ckeditor.addCommand('saveRJS', {
readOnly: 1,
exec: gadget.deferNotifySubmit.bind(gadget)
});
gadget.ckeditor.ui.addButton('Save', {
label: "Save",
command: 'saveRJS',
toolbar: 'document,1'
});
gadget.ckeditor.on('instanceReady', function (event) {
event.editor.execCommand('maximize');
});
gadget.ckeditor.on('change', gadget.deferNotifyChange.bind(gadget));
}
if (modification_dict.hasOwnProperty('value')) {
this.ckeditor.setData(this.state.value);
}
})
.declareService(function () {
var result,
event,
context = this;
function extractSizeAndDispatch() {
if (MATCH_MEDIA.matches) {
return context.changeState({
is_mobile: true
});
}
return context.changeState({
is_mobile: false
});
}
result = loopEventListener(window, 'resize', false,
extractSizeAndDispatch);
event = document.createEvent("Event");
event.initEvent('resize', true, true);
window.dispatchEvent(event);
return result;
});
}(window, document, rJS, CKEDITOR, RSVP));
\ No newline at end of file
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="File" module="OFS.Image"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_Cacheable__manager_id</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>__name__</string> </key>
<value> <string>ckeditor.gadget.js</string> </value>
</item>
<item>
<key> <string>content_type</string> </key>
<value> <string>application/javascript</string> </value>
</item>
<item>
<key> <string>precondition</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string></string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment