Override default component settings in grapesjs? - grapesjs

I am using GrapesJS in a CMS. By default, added blocks come with component settings defined in this file:
https://github.com/artf/grapesjs/blob/dev/src/dom_components/model/Component.js
How do I override the default component settings so they can be applied globally to all components within my custom blocks?

This is how I do it:
grapesEditor.BlockManager.get('image').set({
content: { style: 'color: "black"; max-width: 962px;' },
});
Where grapesEditor is the instance of the editor that you get when initalizing it.

Is there a way to update defaults for built-in components? I have bold text inside element. All bold elements should have default highlighted: false. I tried this config but no success
Editor.DomComponents.addType('text', {
model: {
defaults: {
tagName: 'b',
highlightable: false,
}
}
});
I don't use any storageManager and elements b, i etc. are always highlighted. When I use storageManager local, element are ok and not highlighted.

Related

How to make custom theme using Shoutem's StyleProvider that properly uses underlying INCLUDE

I really love the shoutem theme library, but I'm finding it difficult to hook into the recursive INCLUDE that makes the underlying code work beautifully (See code+documentation here: https://github.com/shoutem/theme/blob/develop/src/Theme.js). For instance, if we have:
render() {
return (
<StyleProvider style={theme}>
<View />
</StyleProvider>
);
}
const theme = _.merge(getTheme(), {
'shoutem.ui.Text': {
color: 'green',
},
});
This simple text color change will work, but only for shoutem Text components. However, Heading, Title, Subtitle, etc. all of which pull from Text attributes in the shoutem library because of INCLUDE. The use of a simple _.merge(...) only overwrites the component itself, but not anything that it might subsequently affects. It sounds like I need to overwrite attributes higher up in the tree (e.g., Text), and then regenerate the theme so it affects all "children" that it's included in (e.g., Heading and Title). Using the publicly exposed API, is this possible to do somehow at the moment? Or are there any forks or utilities you're aware of that accomplish this with your library.
There is a text property in the root of the default shoutem ui theme that is included into all text elements (https://github.com/shoutem/ui/blob/develop/theme.js#L292). You should be able to accomplish your use case by simply overriding values from that property:
const theme = _.merge(getTheme(), {
text: {
color: 'green',
},
});
In case you want to create a more complex theme, you can use INCLUDE in your code as well. INCLUDE works by merging all values from top level theme properties it targets. You can use it to include properties from the base theme, and you can also include your own custom properties:
import { INCLUDE } from '#shoutem/theme';
const theme = _.merge(getTheme(), {
// Define a top level property to use in includes
largeText: {
fontSize: 20,
},
'shoutem.ui.Text': {
// Include a text property from the base theme
// and a largeText property defined above
[INCLUDE]: ['text', 'largeText'],
// Override the text color after all includes
// have been resolved
color: 'green',
},
});
Sometimes specific components define styles after INCLUDEs have been resolved, those styles have a higher priority, and will always override the style from INCLUDEs. To change those styles, you can use a createSharedStyle helper:
import { createSharedStyle } from '#shoutem/theme';
const textComponents = [
'shoutem.ui.Heading',
'shoutem.ui.Title',
'shoutem.ui.Subtitle',
'shoutem.ui.Text',
'shoutem.ui.Caption',
];
const theme = _.merge(getTheme(), {
...createSharedStyle(textComponents, {
color: 'green',
},
});
Finally, some more basic customizations can be done through theme variables, you can pass custom variables when calling getTheme(https://github.com/shoutem/ui/blob/develop/theme.js#L55-L144).

Need to set class/id values on buttons in Extjs MessageBox

Our testing team require IDs or class values to be set on the HTML elements in our message popup boxes. This is for their automated tests.
I can pass in a class value for the dialog panel by passing in a cls value like so:
Ext.Msg.show({
title:'Reset Grid Layout',
msg: 'Are you sure that you want to reset the grid layout?',
cls:'Reset-Grid-Layout-Message',
buttons: Ext.Msg.YESNO,
fn: function (response) {
if (response == 'yes') {
}
},
icon: Ext.window.MessageBox.QUESTION
});
Now we also need it on the buttons, and also on the text being displayed. Is there some way of getting a cls value onto the buttons?
I was thinking it may be possible to expand the button parameter into something like :
buttons : [{name:'but1', cls:'asdf'}, {name:'but2', cls:'asdf2'}]
But google is not giving me back anything useful.
If your testing team uses Selenium for their automated test, adding ids/classes in every component could be difficult for both of you.
Overriding components in Ext is a good solution, but I don't recommend this because it will affect all your components. Unless you know what you're doing.
I suggest, extend Ext.window.MessageBox and generate classes for your buttons based on your parent cls.
// Put this somewhere like /custom/messagebox.js
Ext.define('App.MyMessageBox', {
extend: 'Ext.window.MessageBox'
,initConfig: function(config) {
this.callParent(arguments);
}
,makeButton: function(btnIdx) {
var me = this;
var btnId = me.buttonIds[btnIdx];
return new Ext.button.Button({
handler: me.btnCallback
,cls: me.cls + '-' + btnId
,itemId: btnId
,scope: me
,text: me.buttonText[btnId]
,minWidth: 75
});
}
});
To use:
App.Box = new App.MyMessageBox({
cls:'reset-grid-layout'
}).show({
title:'Reset Grid Layout'
,msg: 'Are you sure that you want to reset the grid layout?'
,buttons: Ext.Msg.YESNO
,icon: Ext.window.MessageBox.QUESTION
});
Your buttons will have reset-grid-layout-yes and reset-grid-layout-no class.
You can do the same with other components you have. Check out the Fiddle. https://fiddle.sencha.com/#fiddle/7qb
You should refer to the API
cls : String A CSS class string to apply to the button's main element.
Overrides: Ext.AbstractComponent.cls
You can also use the filter on right side (not the one in the right top corner). Just type cls and you will see all properties, methods and events containing cls (note that you see by default just public members, use the menu on the right of this searchfield to extend this)
Edit
If you just need it for testing purpose I would recommend to override the responsible method. This should work (untested!)
Ext.window.MessageBox.override({
buttonClasses: [
'okCls', 'yesCls', 'noCls', 'cancelCls'
],
makeButton: function(btnIdx) {
var btnId = this.buttonIds[btnIdx];
var btnCls = this.buttonClasses[btnIdx];
return new Ext.button.Button({
handler: this.btnCallback,
cls: btnCls,
itemId: btnId,
scope: this,
text: this.buttonText[btnId],
minWidth: 75
});
}
});

Add a CSS class to the TAB in TabBar, not the tab it self

Here is a screenshot to visualize what I want to do.
There is an extra tab which is iconless (between exit and project).
The blue highlighted line is the element itself in the inspector.
My goal is to set the tab's width in the tabbar and not in the tabpanel to 5px.
So That it would act has a spacer between tabs' icons.
I tried to manually add a CSS class so that I could create a very specific rule pointing to that element and inside this rule set the width to 5px with an !important tag.
.x-tab .x-tab-normal .x-item-disabled .x-iconalign-center .x-tab-icon .x-layout-box-item .x-stretched
{
width:5px !important;
}
Sadly I never found a way to add a class at that particular level of the component hierarchy.
So I tried to replace an existing CSS class of that component (.x-item-disabled).
I changed .x-item-disabled to .fake and than created a CSS rule accordingly...
It did not work and has in the first case, the component's css classes in the inspector did not changed at all..
I'm pretty sure I need to do it that way since it's not something sencha allows us to do.
Can someone help me out plz?
Ext.tab.Bar and Ext.tab.Tab are private classes and Ext.tab.Panel does not seem to expose that feature, so I guess at the moment there is no simple way to do what you ask. Those tabs are built based on the Panel items configuration, but the data you pass in are not directly mapped to them. Indeed if you apply a cls or style property to an item configuration, that goes to the content of the panel, not to its associated tab. You can however modify the tab after your panel has been initialized:
Try this:
Ext.create('Ext.TabPanel', {
fullscreen: true,
tabBarPosition: 'bottom',
defaults: {
styleHtmlContent: true
},
items: [
{
title: 'Home',
iconCls: 'home',
html: 'Home Screen'
},
{
title: '',
iconCls: 'dummy',
html: ''
},
{
title: 'Contact',
iconCls: 'user',
html: 'Contact Screen'
}
],
initialize: function() {
// get spacer by position, it's ugly but it works
// without extending Sencha components
var spacer = this.getTabBar().getAt(1);
// of course here you could apply a CSS class
// if you prefer
spacer.setStyle('width:5px; min-width:5px;');
// let's also disable the button
spacer.setDisabled(true);
// and remove the icon since it is mandatory in Panel
// config but we don't really want it
spacer.setIcon(false);
}
});
See the fiddle.
Add
this.callParent(arguments);
code in your initialize function in answer 1

how to wrap text of selectfield option in sencha touch 2

I'am trying to display Sencha Touch 2 selectfield with very long option text but text gets truncated with Ellipsis, like Very long option t....
How to display couple lines in one option?
Code:
{
xtype: 'selectfield',
options:[
{
text: 'Very long option I wish to splint into two separate lines',
value: 0
},
{
text: 'Another very long option I wish to splint into two separate lines',
value: 1
}
]
}
I've tried using \n and <br/> but is not working.
There are 3 two ways to do this.
use labelWrap config option set to true.
This will avoid truncating text that appears on selectfield initially. Later when you tap on selectfield; you've two choices. Using picker or list. picker will be used only if you set it to true in usePicker config. If you are on tablet, desktop or mobile default list will be shown containing options. Using labelWrap config will not be usefull if options are displayed in list after tap on selectfield.
Use following CSS override to avoid truncating.
.x-list-item-label{
height: 100% !important;
}
.x-list-label{
white-space: pre-wrap !important;
}
This override along with above mentioned labelWrap config set to true will make both list and selectfield display whole text neatly. But this will override styles that may affect appearance of other lists in your app.
Third approach that can be is to override Ext.field.Select and create custom select field. In this style, you need to just override following method - getTabletPicker that generated the list displayed on tap of selectfield. Code from ST source is as fallows -
getTabletPicker: function() {
var config = this.getDefaultTabletPickerConfig();
if (!this.listPanel) {
this.listPanel = Ext.create('Ext.Panel', Ext.apply({
centered: true,
modal: true,
cls: Ext.baseCSSPrefix + 'select-overlay',
layout: 'fit',
hideOnMaskTap: true,
items: {
xtype: 'list',
store: this.getStore(),
itemTpl: '<span class="x-list-label">{' + this.getDisplayField() + ':htmlEncode}</span>',
listeners: {
select : this.onListSelect,
itemtap: this.onListTap,
scope : this
}
}
}, config));
}
return this.listPanel;
}
Check out the line itemTpl and cls config. Here both options set styles that are defined for list. These will decide the appearance of list displayed on tap of selectfield. This approach might sound dirty. But it's useful, if you want to make some drastic changes in appearance and behaviour.

How do I hide the top toolbar of a Ext.Panel? (ExtJS 2.0)

For some reason Ext.Panel.getTopToolbar() is returning an array of objects (the elements of the toolbar, but NOT the toolbar itself) and not an Ext.Toolbar. Because of that, I can't manage to hide an already set toolbar. How should I proceed?
Sample code:
function (panel)
{
alert(panel.getTopToolbar()); // displays the list of elements in the toolbar
panel.getTopToolbar().hide(); // error: "hide" is not a function
}
It should work, so it sounds like maybe you used topToolbar as a config instead of using tbar as the config? If you set a tbar config it gets instantiated and saved as topToolbar which is the Ext.Toolbar instance exposed by getTopToolbar(). If you overwrote topToolbar directly you might see this issue.
You might find this block of code in Panel.onRender (you'll have to include that file directly) and set a breakpoint in Firebug to see what's happening:
if(this.tbar && this.topToolbar){
if(this.topToolbar instanceof Array){
this.topToolbar = new Ext.Toolbar(this.topToolbar);
}
this.topToolbar.render(this.tbar);
}
panel.getTopToolbar().setVisible(false);
In 4.2.1 what works for me is:
var topToolbar = Ext.create('Ext.toolbar.Toolbar', {
dock: 'top',
width: 'auto',
id: 'mytoolbar',
hidden: true,
items: [...]
});
var p = Ext.create('App.view.MyCustomPanel', {
html: 'test',
});
if (userCanSeeToolbar) {
p.addDocked(topToolbar);
}
Then dynamically I can show/hide the top toolbar:
/* if (userCanSeeToolbar) { */
p.getDockedComponent('mytoolbar').show();
p.getDockedComponent('mytoolbar').hide();

Resources