CKEDITOR plain text - ckeditor

Is there anyway to force the CKEDITOR to just be plain text when I enter this TextEnter it sends out this <p>TextEnter</p>\n. I wanted to see if any of the config setting can help me with that.
CKEDITORInitializer() {
if ((<any>window).CKEDITOR.instances.indicationElementId)
(<any>window).CKEDITOR.instances.indicationElementId.destroy();
(<any>window).CKEDITOR.disableAutoInline = true;
(<any>window).CKEDITOR.config.forcePasteAsPlainText = true;
(<any>window).CKEDITOR.config.autoParagraph = false;
(<any>window).CKEDITOR.replace("indicationElementId", {
height: '60',
toolbar: [
{ name: 'insert', items: ['SpecialChar'] },
],
specialChars: ['©', '®', '–', '¾', '≥', '≤'],
});
(<any>window).CKEDITOR.instances["indicationElementId"].on("change", () => {
this.ngZone.run(() => {
this.item.ValueName = this.getContent();
this.indicationContentChanged.next(null);
});
});
}

Related

ReactNavigator -StackNavigator how to use diffrent animation with only specific screen

using
"react-navigation": "^4.0.10",
"react-navigation-stack": "^1.10.3",
import {
createStackNavigator, StackViewTransitionConfigs,
} from 'react-navigation-stack';
const HomeStackNavigator = createStackNavigator({
List:ListContainer,
Detail:DetailContainer,
Modal: {
screen: ModalContainer,
navigationOptions: {
...StackViewTransitionConfigs.ModalSlideFromBottomIOS,
},
},
}, {
mode: 'card',
headerMode: 'none',
defaultNavigationOptions: {
gestureEnabled: true,
...StackViewTransitionConfigs.SlideFromRightIOS,
},
});
All other screens open in the form of a card, and I want to open only one specific screen in modal form.
i tried
const HomeStackNavigator = createStackNavigator({
List:ListContainer,
Detail:DetailContainer,
},
}, {
mode: 'card',
headerMode: 'none',
defaultNavigationOptions: {
gestureEnabled: true,
...StackViewTransitionConfigs.SlideFromRightIOS,
},
});
const HomeStackNavigator2 = createStackNavigator({
Home:HomeStackNavigator,
Modal: {
screen: ModalContainer,
},
}, {
mode: 'modal',
headerMode: 'none',
});
The first code failed because all the arcs were opened in card format.
In the second code I tried, the screen I wanted was opened in modal form, but when I moved from modal to detail, the modal was closed.
In the first code, is it possible to open only the modal screen in modal form?
I solved it this way.
import {
createStackNavigator, StackViewTransitionConfigs, StackViewStyleInterpolator,
} from 'react-navigation-stack';
const transitionConfigs = (props) => {
const { scene } = props;
const { route } = scene;
const params = route.params || {};
const transition = params.transition || 'forHorizontal';
if (transition === 'forVertical') {
return StackViewTransitionConfigs.ModalSlideFromBottomIOS;
}
return StackViewTransitionConfigs.SlideFromRightIOS;
};
const HomeStackNavigator = createStackNavigator({
List:ListContainer,
Detail:DetailContainer,
Modal: {
screen: ModalContainer,
},
}, {
mode: 'card',
headerMode: 'none',
transitionConfig:transitionConfigs,
});
Change animation by sending trasition:'forVertical' to params when navigate.

Laravel vue stripe: how to pass client_secret PaymentIntent from clientside to serverside?

I'm using stripe with laravel and vue js. Stripe support told me that I have to implent the paymentIntent function. All the code works fine, the problem is that on the server side I have to pass the client_secre and I dont know how to do it...
Here's the code...
SERVER SCRIPT
\Stripe\Stripe::setApiKey('MY_KEY');
try {
\Stripe\PaymentIntent::create([
'currency' => 'EUR',
'amount' => $request->amount * 100,
'description' => 'Donazione',
'metadata' => [
'customer' => $request->name,
'integration_check' => 'accept_a_payment'
]
]);
CLIENT SIDE SCRIPT
import { Card, createToken } from 'vue-stripe-elements-plus'
export default {
components: { Card },
data () {
return {
complete: false,
errorMessage: '',
stripeOptions: {
// see https://stripe.com/docs/stripe.js#element-options for details
style: {
base: {
color: '#32325d',
lineHeight: '18px',
fontFamily: '"Raleway", Helvetica, sans-serif',
fontSmoothing: 'antialiased',
fontSize: '16px',
'::placeholder': {
color: '#aab7c4'
}
},
invalid: {
color: '#fa755a',
iconColor: '#fa755a'
}
},
hidePostalCode: true
}
}
},
methods: {
pay () {
//createToken().then(data => console.log(data.token))
// Instead of creatToken I have to use confirmCardPayment() and pass the client_secret
},
change(event) {
// if (event.error) {
// this.errorMessage = event.error.message;
// } else {
// this.errorMessage = ''
// }
this.errorMessage = event.error ? event.error.message : ''
}
}
}
I recently had to set this up in my platform and here is how I did it. I created a controller called:
PaymentIntentController.php
Stripe::setApiKey(env('STRIPE_SECRET'));
$payment_intent = PaymentIntent::create([
'payment_method_types' => ['card'],
'amount' => $request->invoice['total'] * 100,
'currency' => $this->currency($request),
'receipt_email' => $request->invoice['clients_email']
],
[
'stripe_account' => $request->user['stripe_user_id']
]);
return $payment_intent;
On the client-side, you need to have an Axios request hit this controller so you can get the payment_intent.
Like this:
loadPaymentIntent () {
axios.post('/api/stripe/connect_payment_intent', {'invoice': this.invoice, 'user': this.user}).then((response) => {
this.paymentIntent = response.data
})
},
I have my payment intent setup to load when a checkout form is displayed. Then when the form is submitted we have access to the payment_intent which we can use in the confirmCardPayment method like such:
submit () {
let self = this
self.isLoading = true
self.stripe.confirmCardPayment(self.paymentIntent.client_secret, {
return_url: self.returnUrl + `/clients/${self.invoice.client_id}/invoices/${self.invoice.id}`,
receipt_email: self.invoice.clients_email,
payment_method: {
card: self.card,
billing_details: {
name: self.formData.name,
}
}
}).then(function(result) {
if (result.error) {
self.isLoading = false
self.cardError.status = true
self.cardError.message = result.error.message
setTimeout(() => {
self.cardError = {}
}, 3000)
} else {
if (result.paymentIntent.status === 'succeeded') {
self.handleInvoice(result.paymentIntent)
self.closeModal()
setTimeout(() => {
location.href = self.returnUrl + `/clients/${self.invoice.client_id}/invoices/${self.invoice.id}?success=true`
}, 1000)
}
}
});
},

CKEditor add Format combo items inside context (nested) menu

I am using CKEditor 4.5.7 in one of my project. We have customized Format combo as shown in the below screen shot, the ask is to have all the items appearing inside this combo on right click.
And below is the code for Format combo:
config.format_tags = 'p;h3;h4;pre;ImageInline;ImageCentered;ImageCenteredWithDropShadow;FigureHeading;Equation;EquationDefinition;TableWithoutBorder';
config.format_ImageInline = { name: 'Image inline', element: 'img', attributes: { 'class': 'noborder' } };
config.format_ImageCentered = { name: 'Image centered', element: 'img', attributes: { 'class': 'noborderblock' } };
config.format_ImageCenteredWithDropShadow = { name: 'Image centered drop shadow', element: 'img', attributes: { 'class': 'border' } };
config.format_FigureHeading = { name: 'Figure/Table heading', element: 'p'/*['p', 'td']*/, attributes: { 'class': 'footing' } };
config.format_Equation = { name: 'Equation', element: 'table', attributes: { 'class': 'equation' } };
config.format_EquationDefinition = { name: 'Equation definition', element: 'table', attributes: { 'class': 'where' } };
config.format_TableWithoutBorder = { name: 'Table without border', element: 'table', attributes: { 'class': 'nobordertable' } };
I was able to get them displayed in context menu as shown in below screen shot:
But I am not sure what will be the command name for each one of them. i.e.
command: 'format_ImageCentered' /*I need help here*/
command: 'format_ImageCenteredWithDropShadow' /*I need help here*/
I have already downloaded full source code of CKEditor and gone thru ckeditor\plugins\format\plugin.js but wasn't able to figure out what to specify as command.
Below is my code for customizing Context menu:
var ck_article = CKEDITOR.replace("content", { customConfig: '<config js file path>', bodyClass: '<css class>' });
ck_article.on("instanceReady", function (evt) {
var editor = evt.editor;
/*Code for checking if editor has context menu or not removed for brevity*/
//...
//...
editor.addMenuGroup('ck_group');
editor.addMenuItem('bold', {
label: 'Bold',
command: 'bold',
group: 'ck_group'
});
editor.addMenuItem('iconselector', {
label: '...',
command: 'iconselector',
group: 'ck_group'
});
editor.addMenuItem('numberedlist', {
label: 'Numbered List',
command: 'numberedlist',
group: 'ck_group'
});
editor.addMenuItem('bulletedlist', {
label: 'Bulleted List',
command: 'bulletedlist',
group: 'ck_group'
});
editor.addMenuItem('link', {
label: 'Link',
command: 'link',
group: 'ck_group'
});
editor.addMenuItems({
formatting: {
label: 'Formatting',
group: 'ck_group',
getItems: function () {
var selection = editor.getSelection();
//This is to nest items inside context menu of CKEditor
return {
format_ImageCentered: CKEDITOR.TRISTATE_ON,
format_ImageCenteredWithDropShadow: CKEDITOR.TRISTATE_ON
}
}
},
format_ImageCentered: {
label: "Image centered",
group: 'ck_group',
command: 'format_ImageCentered' /*I need help here*/
},
format_ImageCenteredWithDropShadow: {
label: "Image centered drop shadow",
group: 'ck_group',
command: 'format_ImageCenteredWithDropShadow' /*I need help here*/
}
});
editor.contextMenu.addListener(function (element, selection, elementPath) {
var contentMenuItems = {
link: CKEDITOR.TRISTATE_ON,
bold: CKEDITOR.TRISTATE_ON,
numberedlist: CKEDITOR.TRISTATE_ON,
bulletedlist: CKEDITOR.TRISTATE_ON,
iconselector: CKEDITOR.TRISTATE_ON,
formatting: CKEDITOR.TRISTATE_ON
};
if (element.getAscendant('a', true)) {
//If we are already inside 'a' tag then remove link from Context menu else we will end up with two "Link" menus
delete contentMenuItems.link
}
if ($.trim(selection.getSelectedText()) === '') {
//If no text is selected then remove bold from context menu
delete contentMenuItems.bold;
//contentMenuItems.bold = CKEDITOR.TRISTATE_DISABLED; //This doesn't work as the menu item is disabled but hover effect is still there
//Similarly remove link if nothing is selected as it will insert hyperlink text as words inside CKEditor
delete contentMenuItems.link;
//contentMenuItems.link = CKEDITOR.TRISTATE_DISABLED; //This doesn't work as the menu item is disabled but hover effect is still there
}
return contentMenuItems;
});
});
References:
I have used below URL as references:
http://blog.ale-re.net/2010/06/ckeditor-context-menu.html
http://docs.ckeditor.com/#!/guide/plugin_sdk_sample_2
CKEditor - Possible to have context menu for basic styles?
I ended up creating plugin for each and every option listed in Format combo. If there is any other better way than this then please let me know. I am passing code just in case if someone else stumbles with the similar issue.
Below screen shot shows how the plugin folder looks inside CKEditor folder:
I am pasting just one plugin code as all of plugins have the exact same code the only difference is value for pluginName, which is exact same as folder name:
//All the files inside folder stating with context_<name> have exact same code except pluginName variable.
//I need to this to support format inside right click
(function () {
"use strict";
var pluginName = 'contextmenu_tablewithoutborder'; //This name will be used to add to 'config.extraPlugins' string
var commandName = pluginName;
// Register the plugin within the editor.
CKEDITOR.plugins.add(pluginName, {
// Register the icons. They must match command names.
icons: pluginName,
// The plugin initialization logic goes inside this method.
init: function (editor) {
// Define an editor command.
editor.addCommand(commandName, { //Command name must match with name provided in editor.ui.addButton
// Define the function that will be fired when the command is executed.
exec: function (editor) {
if (typeof editor.applyFormatStyles === 'function')
editor.applyFormatStyles(pluginName.split('_')[1]);
else
throw new Error('applyFormatStyles is not defined as function (' + pluginName + ')');
}
});
}
});
})();
I then extended CKEditor and added below methods:
CKEDITOR.editor.prototype.getFormatStyles = function () {
var styles = {}
var editor = this;
var config = editor.config,
lang = editor.lang.format;
// Gets the list of tags from the settings.
var tags = config.format_tags.split(';');
for (var i = 0; i < tags.length; i++) {
var tag = tags[i];
var style = new CKEDITOR.style(config['format_' + tag]);
if (!editor.filter.customConfig || editor.filter.check(style)) {
styles[tag] = style;
styles[tag]._.enterMode = editor.config.enterMode;
}
}
return styles;
}
CKEDITOR.editor.prototype.applyFormatStyles = function (styleName) {
var editor = this;
var styles = editor.getFormatStyles();
editor.focus();
editor.fire('saveSnapshot');
var style = styles[styleName],
elementPath = editor.elementPath();
editor[style.checkActive(elementPath, editor) ? 'removeStyle' : 'applyStyle'](style);
// Save the undo snapshot after all changes are affected. (#4899)
setTimeout(function () {
editor.fire('saveSnapshot');
}, 0);
}
I then modified my config file and added all these plugins as extra plugins:
CKEDITOR.editorConfig = function (config) {
var extraPlugins = [];
//Remove other code for brevity
//...
//...
config.format_tags = 'p;h3;h4;pre;imageinline;imagecentered;imagecenteredwithdropshadow;figureheading;equation;equationdefinition;tablewithoutborder';
config.format_imageinline = { name: 'Image inline', element: 'img', attributes: { 'class': 'noborder' } };
config.format_imagecentered = { name: 'Image centered', element: 'img', attributes: { 'class': 'noborderblock' } };
config.format_imagecenteredwithdropshadow = { name: 'Image centered drop shadow', element: 'img', attributes: { 'class': 'border' } };
config.format_figureheading = { name: 'Figure/Table heading', element: 'p'/*['p', 'td']*/, attributes: { 'class': 'footing' } };
config.format_equation = { name: 'Equation', element: 'table', attributes: { 'class': 'equation' } };
config.format_equationdefinition = { name: 'Equation definition', element: 'table', attributes: { 'class': 'where' } };
config.format_tablewithoutborder = { name: 'Table without border', element: 'table', attributes: { 'class': 'nobordertable' } };
var contextmenu_plugins = config.format_tags.split(";");
for (var i = 0; i < contextmenu_plugins.length; i++) {
var pluginName = contextmenu_plugins[i];
extraPlugins.push("contextmenu_{0}".format(pluginName))
}
config.extraPlugins = extraPlugins.join(',');
}
And then finally when I create editor I extent the context menu. I could add this logic in plugin.js file but since I wanted plugin.js code to be exact same except a line or two's difference I didn't bother adding it there.
var ck_article = CKEDITOR.replace("content", { customConfig: '<config js file path>', bodyClass: '<css class>' });
ck_article.on("instanceReady", function (evt) {
var editor = evt.editor;
editor.addMenuGroup('ck_group');
editor.addMenuItem('bold', {
label: 'Bold',
command: 'bold',
group: 'ck_group'
});
editor.addMenuItem('iconselector', {
label: '...',
command: 'iconselector',
group: 'ck_group'
});
editor.addMenuItem('numberedlist', {
label: 'Numbered List',
command: 'numberedlist',
group: 'ck_group'
});
editor.addMenuItem('bulletedlist', {
label: 'Bulleted List',
command: 'bulletedlist',
group: 'ck_group'
});
editor.addMenuItem('link', {
label: 'Link',
command: 'link',
group: 'ck_group'
});
editor.addMenuItems({
formatting: {
label: 'Formatting',
group: 'ck_group',
getItems: function () {
var selection = editor.getSelection();
//This is to nest items inside context menu of CKEditor
var tags = editor.config.format_tags.split(";");
var menu_items = {
};
for (var i = 0; i < tags.length; i++) {
menu_items[tags[i]] = CKEDITOR.TRISTATE_ON;
}
//menu_items - will have object something like below
//{p: 1, h3: 1, h4: 1......}
return menu_items;
}
},
p: {
label: "Normal",
group: 'ck_group',
command: 'contextmenu_p'
},
h3: {
label: "Heading",
group: 'ck_group',
command: 'contextmenu_h3'
},
h4: {
label: "Sub Heading",
group: 'ck_group',
command: 'contextmenu_h4'
},
pre: {
label: "Formatted",
group: 'ck_group',
command: 'contextmenu_pre'
},
imageinline: {
label: "Image inline",
group: 'ck_group',
command: 'contextmenu_imageinline'
},
imagecentered: {
label: "Image centered",
group: 'ck_group',
command: 'contextmenu_imagecentered'
},
imagecenteredwithdropshadow: {
label: "Image centered drop shadow",
group: 'ck_group',
command: 'contextmenu_imagecenteredwithdropshadow'
},
figureheading: {
label: "Figure/Table heading",
group: 'ck_group',
command: 'contextmenu_figureheading'
},
equation: {
label: "Equation",
group: 'ck_group',
command: 'contextmenu_equation'
},
equationdefinition: {
label: "Equation definition",
group: 'ck_group',
command: 'contextmenu_equationdefinition'
},
tablewithoutborder: {
label: "Table without border",
group: 'ck_group',
command: 'contextmenu_tablewithoutborder'
}
});
editor.contextMenu.addListener(function (element, selection, elementPath) {
var contentMenuItems = {
link: CKEDITOR.TRISTATE_ON,
bold: CKEDITOR.TRISTATE_ON,
numberedlist: CKEDITOR.TRISTATE_ON,
bulletedlist: CKEDITOR.TRISTATE_ON,
iconselector: CKEDITOR.TRISTATE_ON,
formatting: CKEDITOR.TRISTATE_ON
};
if (element.getAscendant('a', true)) {
//If we are already inside 'a' tag then remove link from Context menu else we will end up with two "Link" menus
delete contentMenuItems.link
}
if ($.trim(selection.getSelectedText()) === '') {
//If no text is selected then remove bold from context menu
delete contentMenuItems.bold;
//Similarly remove link if nothing is selected as it will insert hyperlink text as words inside CKEditor
delete contentMenuItems.link;
}
return contentMenuItems;
});
});
I know there is too much of code but I wasn't able to find any other simple way to do this.
When all done this is how it looks:
Quick recap:
Created plugin for each item appearing in Format combo
Only change in all the plugin.js file is pluginName (it is name of the folder)
Extend CKEditor and add applyFormatStyles method which will be invoked by plugin.js file
In your config file add all these as extra plugins
And on creation of CKEditor instance extend context menu

How should I create a Tree structure in Rally of defects with respect to user story

I am able to get tree structure for the user stories but want it same for defects also which are related to particular user story so that at a singe screen I can see both user stories and the related defects.
You may use features: [{ftype:'groupingsummary'}] of ExtJS to group defects by user stories and even summarize by some other field, in the code below by PlanEstimate. To group defects by user story Requirement attribute on defect is used, which points to the related story. In this example defects are filtered by Iteration.
Ext.define('CustomApp', {
extend: 'Rally.app.TimeboxScopedApp',
componentCls: 'app',
scopeType: 'iteration',
comboboxConfig: {
fieldLabel: 'Select Iteration:',
labelWidth: 100
},
onScopeChange: function() {
this.makeStore();
},
makeStore: function() {
var filter = Ext.create('Rally.data.wsapi.Filter', {
property: 'Requirement',
operator: '!=',
value: null
});
filter= filter.and(this.getContext().getTimeboxScope().getQueryFilter());
filter.toString();
Ext.create('Rally.data.wsapi.Store', {
model: 'Defect',
fetch: ['ObjectID', 'FormattedID', 'Name', 'State', 'Requirement', 'PlanEstimate'],
autoLoad: true,
filters: [filter],
listeners: {
load: this.onDataLoaded,
scope: this
}
});
},
onDataLoaded: function(store, records){
if (records.length === 0) {
this.notifyNoDefects();
}
else{
if (this.notifier) {
this.notifier.destroy();
}
var that = this;
var promises = [];
_.each(records, function(defect) {
promises.push(this.getStory(defect, this));
},this);
Deft.Promise.all(promises).then({
success: function(results) {
that.defects = results;
that.makeGrid();
}
});
}
},
getStory: function(defect, scope) {
var deferred = Ext.create('Deft.Deferred');
var that = scope;
var storyOid = defect.get('Requirement').ObjectID;
Rally.data.ModelFactory.getModel({
type: 'HierarchicalRequirement',
scope: this,
success: function(model, operation) {
fetch: ['FormattedID','ScheduleState'],
model.load(storyOid, {
scope: this,
success: function(record, operation) {
var storyScheduleState = record.get('ScheduleState');
var storyFid = record.get('FormattedID');
var defectRef = defect.get('_ref');
var defectOid = defect.get('ObjectID');
var defectFid = defect.get('FormattedID');
var defectPlanEstimate = defect.get('PlanEstimate');
var defectName = defect.get('Name');
var defectState = defect.get('State');
var story = defect.get('Requirement');
result = {
"_ref" : defectRef,
"ObjectID" : defectOid,
"FormattedID" : defectFid,
"Name" : defectName,
"PlanEstimate" : defectPlanEstimate,
"State" : defectState,
"Requirement" : story,
"StoryState" : storyScheduleState,
"StoryID" : storyFid
};
deferred.resolve(result);
}
});
}
});
return deferred;
},
makeGrid: function() {
var that = this;
if (this.grid) {
this.grid.destroy();
}
var gridStore = Ext.create('Rally.data.custom.Store', {
data: that.defects,
groupField: 'StoryID',
pageSize: 1000,
});
this.grid = Ext.create('Rally.ui.grid.Grid', {
itemId: 'defectGrid',
store: gridStore,
features: [{ftype:'groupingsummary'}],
minHeight: 500,
columnCfgs: [
{
text: 'Formatted ID', dataIndex: 'FormattedID', xtype: 'templatecolumn',
tpl: Ext.create('Rally.ui.renderer.template.FormattedIDTemplate')
},
{
text: 'Name', dataIndex: 'Name',
},
{
text: 'State', dataIndex: 'State',
summaryRenderer: function() {
return "PlanEstimate Total";
}
},
{
text: 'PlanEstimate', dataIndex: 'PlanEstimate',
summaryType: 'sum'
},
{
text: 'Story', dataIndex: 'Story',
renderer: function(val, meta, record) {
return '' + record.get('Requirement').FormattedID + '';
}
},
{
text: 'Story Schedule State', dataIndex: 'StoryState',
}
]
});
this.add(this.grid);
this.grid.reconfigure(gridStore);
},
notifyNoDefects: function() {
if (this.grid) {
this.grid.destroy();
}
if (this.notifier) {
this.notifier.destroy();
}
this.notifier = Ext.create('Ext.Container',{
xtype: 'container',
itemId: 'notifyContainer',
html: "No Defects found matching selection."
});
this.add( this.notifier);
}
});

ckeditor with placeholder plguin enhancement double click issue

I need a placeholder/variable that takes name, defaultValue, tooltip/description. I created a plugin and it is working fine in the editor/create mode. When placeholder is created, it is adding the following tags to source
<var class="cke_placeholder" name="varName" title="varToolTip">[[varDefaultValue]]</var>
Image that depicts create & edit mode differences
When I save the html content with placehoder in db and trying to load it back to ckeditor, I am not able to get the + symbol and hence not able to launch the editor.
Here is my ckeditor/plugins/var/plguin.js
'use strict';
( function() {
CKEDITOR.plugins.add( 'var', {
requires: 'widget,dialog',
icons: 'var', // %REMOVE_LINE_CORE%
hidpi: true, // %REMOVE_LINE_CORE%
onLoad: function() {
CKEDITOR.dialog.add( 'var', this.path + 'dialogs/var.js' );
},
init: function( editor ) {
this.registerWidget( editor );
editor.ui.addButton && editor.ui.addButton( 'Var', {
label: 'Create Variable',
command: 'var',
toolbar: 'insert',
icon: 'var'
} );
},
registerWidget: function(editor){
var that = this;
// Put ur init code here.
editor.widgets.add( 'var', {
// Widget code.
dialog: 'var',
pathName: 'var',
// We need to have wrapping element, otherwise there are issues in
// add dialog.
template: '<var class="cke_placeholder">[[]]</var>',
downcast: function() {
return new CKEDITOR.htmlParser.text( '<var class="cke_placeholder" name="'+this.data.name+'" title="'+this.data.description+'">[[' + this.data.defaultValue + ']]</var>' );
},
init: function() {
this.setData( 'defaultValue', this.element.getText().slice( 2, -2 ) );
this.setData( 'name', this.element.getAttribute("name") );
this.setData( 'description', this.element.getAttribute("title") );
},
data: function() {
this.element.setText( '[[' + this.data.defaultValue + ']]' );
this.element.setAttribute('name', this.data.name );
this.element.setAttribute('title', this.data.description );
}
} );
},
afterInit: function( editor ) {
this.registerWidget( editor );
/*var placeholderReplaceRegex = /\[\[([^\[\]])+\]\]/g;
editor.dataProcessor.dataFilter.addRules( {
text: function( text, node ) {
var dtd = node.parent && CKEDITOR.dtd[ node.parent.name ];
// Skip the case when placeholder is in elements like <title> or <textarea>
// but upcast placeholder in custom elements (no DTD).
if ( dtd && !dtd.span )
return;
return text.replace( placeholderReplaceRegex, function( match ) {
// Creating widget code.
var widgetWrapper = null,
innerElement = new CKEDITOR.htmlParser.element( 'span', {
'class': 'cke_placeholder'
} );
// Adds placeholder identifier as innertext.
innerElement.add( new CKEDITOR.htmlParser.text( match ) );
widgetWrapper = editor.widgets.wrapElement( innerElement, 'placeholder' );
// Return outerhtml of widget wrapper so it will be placed
// as replacement.
return widgetWrapper.getOuterHtml();
} );
}
} );*/
}
} );
} )();
Here is my ckeditor/plugins/var/dialogs/var.js
'use strict';
CKEDITOR.dialog.add( 'var', function( editor ) {
//var lang = editor.lang.var,
//generalLabel = editor.lang.common.generalTab,
var generalLabel = 'General',
validRegex = /^[^\[\]<>]+$/,
emptyOrInvalid = ' can not be empty. It can not contain any of following characters: [, ], <, >',
invalid = ' can not contain any of following characters: [, ], <, >';
return {
title: 'Variable properties',
minWidth: 300,
minHeight: 80,
contents: [
{
id: 'info',
label: generalLabel,
title: generalLabel,
elements: [
// Dialog window UI elements.
{
id: 'name',
type: 'text',
style: 'width: 100%;',
label: 'Name',
'default': '',
required: true,
validate: CKEDITOR.dialog.validate.regex( validRegex, 'name'+emptyOrInvalid ),
setup: function( widget ) {
this.setValue( widget.data.name );
},
commit: function( widget ) {
widget.setData( 'name', this.getValue() );
}
},
{
id: 'defaultValue',
type: 'text',
style: 'width: 100%;',
label: 'Default Value',
'default': '',
required: true,
validate: CKEDITOR.dialog.validate.regex( validRegex, 'Default Value'+emptyOrInvalid ),
setup: function( widget ) {
this.setValue( widget.data.defaultValue );
},
commit: function( widget ) {
widget.setData( 'defaultValue', this.getValue() );
}
},
{
id: 'description',
type: 'text',
style: 'width: 100%;',
label: 'Description',
'default': '',
required: true,
validate: CKEDITOR.dialog.validate.regex( validRegex, 'Description'+invalid ),
setup: function( widget ) {
this.setValue( widget.data.description );
},
commit: function( widget ) {
widget.setData( 'description', this.getValue() );
}
}
]
}
]
};
} );

Resources