How do I add toolbar buttons to a custom tinymce dropdown menu? - javascript

I've created a custom dropdown in tinymce like this:
tinymce.init({
toolbar: "alignment",
setup: function(editor) {
editor.addButton('alignment', {
type: 'menubutton',
text: 'Alignment',
icon: false,
menu: [
{ text: 'left', onclick: function() {tinymce.activeEditor.formatter.toggle('alignleft');}},
{ text: 'center', onclick: function() {tinymce.activeEditor.formatter.toggle('aligncenter');}},
{ text: 'right', onclick: function() {tinymce.activeEditor.formatter.toggle('alignright');}},
{ text: 'justify', onclick: function() {tinymce.activeEditor.formatter.toggle('alignjustify');}},
]
});
}
});
which creates this:
However what I'd like is to just move the alignment buttons from the main toolbar in the dropdown menu.
How do I got about putting these actual buttons from the toolbar, into a dropdown menu? Is it like the code above or is a a totally different way?
So basically put these buttons in the dropdown above with the toggle states for on and off too.

Try this setup - Plunker
tinymce.init({
selector: "textarea",
toolbar: "styleselect | bold italic | alignment | alignmentv2",
setup: function(editor) {
editor.addButton('alignment', {
type: 'listbox',
text: 'Alignment',
icon: false,
onselect: function(e) {
tinyMCE.execCommand(this.value());
},
values: [
{icon: 'alignleft', value: 'JustifyLeft'},
{icon: 'alignright', value: 'JustifyRight'},
{icon: 'aligncenter', value: 'JustifyCenter'},
{icon: 'alignjustify', value: 'JustifyFull'},
],
onPostRender: function() {
// Select the firts item by default
this.value('JustifyLeft');
}
});
editor.addButton('alignmentv2', {
type: 'menubutton',
text: 'Alignment v2',
icon: false,
menu: [
{icon: 'alignleft', onclick: function() { console.log(editor); tinyMCE.execCommand('JustifyLeft'); }},
{icon: 'alignright', onclick: function() { tinyMCE.execCommand('JustifyRight'); }}
]
});
}
});

#NoBugs, you can enhance the onselect method to perform the alignment icon update.
At first, by examining structure of this object in the onselect method we'll see that this.settings.values property stores an array with early defined values.
By using one of many find utility functions we get the selected value item and update the icon as needed:
onselect: function() {
selectedItem = find(this.settings.values, {value: this.value()})
this.icon(selectedItem.icon)
tinyMCE.execCommand(this.value());
}
Hope, this helps. Cheers!

This is probably best solved using a custom split button. That way we can assign the last selected option to the main button.
See the result here - CodePen
tinymce.init({
selector: '#editor',
menubar: false,
toolbar: 'bold italic underline | alignmentsplit | bullist numlist outdent indent',
setup: function (editor) {
editor.on('init', function() {
this.getDoc().body.style.fontSize = '16px';
this.getDoc().body.style.fontFamily = 'Georgia';
});
editor.addButton('alignmentsplit', {
type: 'splitbutton',
text: '',
icon: 'alignleft',
onclick: function(e) {
tinyMCE.execCommand(this.value);
},
menu: [{
icon: 'alignleft',
text: 'Align Left',
onclick: function() {
tinyMCE.execCommand('JustifyLeft');
this.parent().parent().icon('alignleft');
this.parent().parent().value = 'JustifyLeft'
}
}, {
icon: 'alignright',
text: 'Align Right',
onclick: function() {
tinyMCE.execCommand('JustifyRight');
this.parent().parent().icon('alignright');
this.parent().parent().value = 'JustifyRight';
}
}, {
icon: 'aligncenter',
text: 'Align Center',
onclick: function() {
tinyMCE.execCommand('JustifyCenter');
this.parent().parent().icon('aligncenter');
this.parent().parent().value = 'JustifyCenter';
}
}, {
icon: 'alignjustify',
text: 'Justify',
onclick: function() {
tinyMCE.execCommand('JustifyFull');
this.parent().parent().icon('alignjustify');
this.parent().parent().value = 'JustifyFull';
}
}
],
onPostRender: function() {
// Select the first item by default
this.value ='JustifyLeft';
}
});
}
});
Note: If you re-select an alignment option on content that is already aligned that way, TinyMCE toggles the alignment formatting off. This is default TinyMCE behaviour, but you would need to indicate that the section already has that formatting via a toggle state on the button for this to make more sense to the user. This has not been implemented above.

Related

How to set ariaLabel for toast and Messagebox

I have a Ext.toast and Ext.Msg to be displayed on button click. So on click of button the content of toast and messagebox should be read.
I have applied ariaLabel but its still not readable, tried setting focus and containsFocus as well but still no luck, when I set defaultFocus:1 on messagebox it works for the first time only. Any hints please.
Ext.toast({
html: 'Data Saved',
title: 'My Title',
width: 200,
align: 't',
ariaLabel: 'My Title Data Saved'
});
Ext.Msg.show({
title: 'Invalid search criteria',
msg: 'check',
ariaLabel:'Invalid search criteria check',
icon: Ext.Msg.ERROR,
buttons: Ext.Msg.OK
});
Screen reader to be used - NVDA
Fiddle can be found here
The problem is that attribute aria-labelledby is always set automatically. (and has the higher precedence ariaLabelledBy). I did not find a way to avoid automatic substitution, so I created an override that does this for window instances
Ext.define('Ext.window.WindowAriaOverride', {
override: 'Ext.window.Window',
afterShow: function () {
this.el.dom.setAttribute('aria-labelledby', null)
this.el.dom.setAttribute('aria-label', this.ariaLabel)
}
});
Fiddle
If you will look at the documentation of the Ext.Msg.show, you will not find there any aria* config/param. This config is available only to Ext.window.MessageBox class.
I have changed your fiddle example to force it work, but unfortunately this aria features looks like to be buggy.
Ext.application({
name: 'Fiddle',
launch: function () {
Ext.create('Ext.Button', {
text: 'toast',
renderTo: Ext.getBody(),
handler: function () {
Ext.create('Ext.window.Toast', {
html: 'Data Saved',
title: 'My Title',
width: 200,
align: 't',
containsFocus: true,
closeAction: 'destroy',
ariaLabel: 'ARIA_LABEL_VALUE',
//ariaLabelledBy: 'ARIA_LABELLED_BY',
ariaDescribedBy: "ARIA_DESCRIBED_BY",
listeners: {
show: function () {
console.log(
this.el.dom.getAttribute('aria-label'),
this.el.dom.getAttribute('aria-labelledby'),
this.el.dom.getAttribute('aria-describedby')
);
}
}
}).show();
}
});
Ext.create('Ext.Button', {
text: 'msgbox',
renderTo: Ext.getBody(),
handler: function () {
Ext.create('Ext.window.MessageBox', {
closeAction: 'destroy',
ariaLabel: 'ARIA_LABEL_VALUE',
//ariaLabelledBy: 'ARIA_LABELLED_BY',
ariaDescribedBy: "ARIA_DESCRIBED_BY",
listeners: {
show: function () {
console.log(
this.el.dom.getAttribute('aria-label'),
this.el.dom.getAttribute('aria-labelledby'),
this.el.dom.getAttribute('aria-describedby')
);
}
}
}).show({
title: 'Invalid search criteria',
cls: 'error-message',
msg: 'yooo',
containsFocus: true,
ariaLabel: 'msg yoo',
modal: true,
icon: Ext.Msg.ERROR,
buttons: Ext.Msg.OK,
});
}
});
}
});
fiddle

ExtJS Toolbar: how keep an item always directly accesible, never put in the "more" menu

I have an ExtJS toolbar at the top of my panel that can have between 5 and 10 actions (buttons), plus a search text field as the last item.
Depending on the size of the window, all items may fit directly on the toolbar, or some of them may get put into a "more" menu button. I need to specify one of those button to have some sort of priority so it is the last one to be put on the "more" button. Or even to never be put on it.
Is there any way to achieve this?
Solution:
Add items with code. I don't know if this is exactly your case, but I often use this to arrange buttons in toolbar:
Working example:
Ext.onReady(function(){
Ext.QuickTips.init();
Ext.FocusManager.enable();
Ext.Ajax.timeout = 100 * 1000;
Ext.define('Trnd.TestWindow', {
extend: 'Ext.window.Window',
closeAction: 'destroy',
border: false,
width: 400,
height: 500,
modal: true,
closable: true,
resizable: true,
layout: 'fit',
fillToolbar: function() {
var me = this;
me.toolbar.add(me.button5);
me.toolbar.add(me.button1);
me.toolbar.add(me.button2);
me.toolbar.add(me.button3);
me.toolbar.add(me.edit);
me.toolbar.add(me.button4);
},
initComponent: function() {
var me = this;
me.callParent(arguments);
me.button1 = Ext.create('Ext.button.Button', {
text: 'Button 1'
});
me.button2 = Ext.create('Ext.button.Button', {
text: 'Button 2'
});
me.button3 = Ext.create('Ext.button.Button', {
text: 'Button 3'
});
me.button4 = Ext.create('Ext.button.Button', {
text: 'Button 4'
});
me.button5 = Ext.create('Ext.button.Button', {
text: 'Button 5'
});
me.edit = Ext.create('Ext.form.TextField', {
text: 'Edit'
});
me.toolbar = Ext.create('Ext.toolbar.Toolbar', {
enableOverflow: true,
items: []
});
me.panel = Ext.create('Ext.panel.Panel', {
tbar: me.toolbar
});
me.add(me.panel);
me.fillToolbar();
}
});
var win = new Trnd.TestWindow({
});
win.show();
});
Notes:
Tested with ExtJS 4.2
I solved this by wrapping the toolbar in a container like this:
tbar: [
{
xtype: 'container',
layout: {
type: 'hbox',
pack: 'start',
align: 'stretch'
},
items: [
{
xtype: 'mail-compose-toolbar',
flex: 1
},
{
xtype: 'mail-compose-search',
itemId: 'mailComposeSearch',
width: 200
}
]
}
]
The search field is of fixed width and the toolbar has a flex:1 so it stretches.

TinyMCE focus in and focus out loop

I have a problem with TinyMCE 4.x and its behavior. Whenever I initialize TinyMCE on popup i get focus in and focus out loop and its looks like flickering.
Here is a gif that shows exactly what is happening. You can see that on main page where i initialize TinyMCE everything is fine and its working as expected, but on popup its kinda start focusing in and out. You can see it in developer tool as well, that class for it changes from mce-content-body to mce-content-body mce-edit-focus and then back.
Here is code how I initialize the TinyMCE.:
initializeTinyMCE(element){
var self = this;
if (element == 'p') {
var toolbar = 'forecolor | fontsizeselect fontselect | align | bold italic underline | bullist numlist | link | strokes | done';
} else if (element == 'h') {
var toolbar = 'forecolor | fontsizeselect | fontselect | H | align | bold italic underline | link | strokes | done';
}
if(self.el.parent().hasClass('popup_content')){
var inline = false
} else {
var inline = true
}
tinyMCE.init({
selector: `#${self.el.find('.content_element').attr('id')}`,
auto_focus: self.testFocus(self.el.find('.content_element').attr('id')),
content_css : 'assets/tinymce/custom/fonts.css',
inline: true,
menubar: false,
theme: 'modern',
skin: 'pagesource',
plugins: ['lists link textcolor colorpicker strokes'],
toolbar: toolbar,
fontsize_formats: '8px 10px 12px 14px 18px 24px 36px 48px',
setup: function (editor) {
self.clonedEl = self.el.clone()
editor.addButton('align', {
type: 'menubutton',
text: '',
icon: 'alignleft',
menu: [{
text: '',
icon: 'alignleft',
onclick: function () {
editor.execCommand('JustifyLeft');
}
}, {
text: '',
icon: 'aligncenter',
onclick: function () {
editor.execCommand('JustifyCenter');
}
}, {
text: '',
icon: 'alignright',
onclick: function () {
editor.execCommand('JustifyRight');
}
}, {
text: '',
icon: 'alignjustify',
onclick: function () {
editor.execCommand('JustifyFull');
}
}]
}),
editor.addButton('H', {
type: 'menubutton',
text: 'H',
icon: false,
menu: [{
text: 'H1',
onclick: function() {
editor.execCommand('FormatBlock', false, 'h1');
}
}, {
text: 'H2',
onclick: function() {
editor.execCommand('FormatBlock', false, 'h2');
}
}, {
text: 'H3',
onclick: function() {
editor.execCommand('FormatBlock', false, 'h3');
}
}, {
text: 'H4',
onclick: function() {
editor.execCommand('FormatBlock', false, 'h4');
}
}, {
text: 'H5',
onclick: function() {
editor.execCommand('FormatBlock', false, 'h5');
}
}, {
text: 'H6',
onclick: function() {
editor.execCommand('FormatBlock', false, 'h6');
}
}]
});
editor.addButton('done', {
text: 'Done',
icon: false,
onclick: function () {
tinyMCE.remove();
self.openEditManager();
self.el.find('.ui-resizable-handle').removeClass('hidden');
}
});
editor.on('remove', function(ed) {
self.removeTinyMCE(ed);
window.historyMem.addRecord(self.clonedEl, self.el.clone())
});
},
init_instance_callback: function (editor) {
editor.on('focus', function (e) {
console.log(2)
});
}
});
}
And this is the element and structure on which the problem persists:
<div class="body_wrapper">
<div class="project_wrapper" data-uuid="<%= #page.uuid %>">
<div class="edit_grid">
<div class="popup_editor">
<div class="popup">
<div class="popup_content">
<div class='widget'>
<div class='tinymce_editor'> # this is the element
</div>
</div>
</div>
</div>
</div>
</div>
</div>
Note: When not doing inline editor it works fine.
I don't need exact solution, any suggestions and ideas would be appreciated. I have tried almost everything, like moving editor popup in different position in DOM, stripping all of the settings, etc. Thank you.

Disable a Dialog Button in CKEditor

I try to write a plugin for the CKEditor (Version 4.x), with a Dialog UI element.
the definition of the dialog looks like:
CKEDITOR.dialog.add('abbrDialog', function(editor) {
return {
title: editor.lang.abbr.title,
label: editor.lang.abbr.title,
minWidth: 400,
minHeight: 200,
contents: [{
id: 'abbreviation-dialog',
label: editor.lang.abbr.label,
elements: [
{
id: 'abbreviation-found-label',
type: 'html',
label: editor.lang.abbr.found,
html: '<span id="foundLabelId">'+ editor.lang.abbr.found + '<\/span>'
},
{
id: 'abbreviation-current-item',
type: 'html',
label: editor.lang.abbr.currentLabel,
html: '<span id="currentLabelId">'+ editor.lang.abbr.currentLabel + '<\/span>'
},
{
id: 'abbreviation-replace-button',
type: 'checkbox',
label: editor.lang.abbr.replaceButton,
onClick : function() {
replaceAbbreviation(editor.lang.abbr.currentLabel, editor.lang.abbr.noMore);
}
},
{
id: 'abbreviation-next-button',
type: 'button',
label: editor.lang.abbr.nextButton,
onClick : function() {
nextAbbreviation(editor.lang.abbr.currentLabel, editor.lang.abbr.noMore);
}
},
{
id: 'abbreviation-all-button',
type: 'button',
label: editor.lang.abbr.allButton,
onClick : function() {
replaceAllAbbreviations(editor.lang.abbr.currentLabel, editor.lang.abbr.noMore);
//alert('Replace all!!');
}
}]
}],
buttons: [CKEDITOR.dialog.okButton],
onShow: function() {
initDialog(editor.lang.abbr.found, editor.lang.abbr.currentLabel);
},
onOk: function() {
// nothing to do
}
In one function i try to disable a button. This looks like:
CKEDITOR.dialog.getCurrent().getContentElement("abbreviation-dialog", "abbreviation-replace-button").disable();
Unfortunately this button gets not disable (but the additional CSS-class cke_disabled is added).
Also strange: if i turn that abbreviation-replace-button into a checkbox, this checkbox gets disabled (with no further code modifications).
My Questions:
How can i disable a button on a plugin dialog?
Why gets the checkbox disabled but the button not?
Where is my mistake?
I think you need to call a special method to disable buttons,
i.e. `disableButton('btn')
you can disable ok or cancel button by following way
CKEDITOR.dialog.getCurrent().disableButton('ok')
CKEDITOR.dialog.getCurrent().disableButton('cancel')
in your case you can try
CKEDITOR.dialog.getCurrent().disableButton('abbreviation-next-button')

How to show a overlay when Panel is clicked in Sencha Touch 2

I have an ActionSheet and a Panel in Sencha Touch 2. I want to show the ActionSheet overlay when the icon-map is clicked in the panel, how can I do that?
Panel.js
Ext.define('app.view.principalTabPanel', {
extend: 'Ext.tab.Panel',
config: {
ui: 'light',
items: [
{
xtype: 'mappanel',
title: 'Map',
iconCls: 'locate'
}
],
tabBar: {
docked: 'bottom',
ui: 'light'
}
}
});
asking.js
Ext.define('app.view.takePhoto', {
extend: 'Ext.ActionSheet',
config: {
items: [
{
text: 'Delete draft',
ui : 'decline'
},
{
text: 'Save draft'
},
{
text: 'Cancel',
ui : 'confirm'
}
]
}
});
You can do this by adding a listener to your tab inside the tab object of your item.
{
xtype: 'mappanel',
title: 'Map',
iconCls: 'locate'
tab: {
listeners: {
tap: function() {
var sheet = Ext.create('app.view.takePhoto');
sheet.show();
}
}
}
}
Inside that listener, we create a new instance of your app.view.takePhoto class and show it.
I ran into the same problem after changing show() to showBy().
Specifying the html id instead of the component did the trick
.showBy(Ext.get('ext-tab-5'));
instead of
.showBy('settingsTab')
seems like the method can only be called on DOM elements.
Hope this helps somehow.

Categories

Resources