How to change the default position of button tooltips in CKEditor 5 - tooltip

Having a small issue with tooltips in the editor, read the api but can't understand what it is saying and I can't seem to find examples anywhere that I can understand either.
I have set up a Classic Editor build, and all the buttons on the toolbar have tooltips with the default position below the button, I want to be able, just for this one instance of the editor, to change the tooltip position to above the buttons instead. The instance is set up like this:
ClassicEditor.create( document.querySelector( '#content' ) )
.then( editor => {
console.log( 'Editor was initialized', editor );
this.annEditorInstance = editor;
} )
.catch( err => {
console.error( err.stack );
} );
That creates an editor instance that is set up exactly as I want, except for the issue with the tooltip. How do I change this? Thanks in advance.

There are two approaches to the problem:
CSS
Tooltips elements have either .ck-tooltip_s or .ck-tooltip_n class. By default all CKEditor 5 tooltips have the former so you could override it in your styles and make it act like the later:
<style>
.ck.ck-tooltip.ck-tooltip_s {
bottom: auto;
top: calc(-1 * var(--ck-tooltip-arrow-size));
transform: translateY( -100% );
}
.ck.ck-tooltip.ck-tooltip_s .ck-tooltip__text::after {
top: auto;
bottom: calc(-1 * var(--ck-tooltip-arrow-size));
transform: translateX( -50% );
border-color: var(--ck-color-tooltip-background) transparent transparent transparent;
border-width: var(--ck-tooltip-arrow-size) var(--ck-tooltip-arrow-size) 0 var(--ck-tooltip-arrow-size);
}
</style>
JS
The UI of the editor is an MVC(VM) structure. The position of the tooltip can be controlled using the JS and the Button#tooltipPosition property ('s' or 'n').
E.g. you can access the toolbar UI elements using editor.ui.view.toolbar and change their properties:
editor.ui.view.toolbar.items.map( item => item.tooltipPosition = 'n' )
but note that not all toolbar items are buttons. Some, for instance, are dropdowns so you'd need to use item.buttonView.tooltipPosition = 'n' in that case. So unless you really want to use JS, I'd go with a simple CSS solution.

Related

Add class/id to path in TinyMCE4

Quick question:
Is there a way to add class and/or ID of the elements in the path of TinyMCE status bar under content?
TinyMCE has no such capability built into its status bar. If you wanted to add that you could do so by modifying the code. I would note that with any type of longer ID or Class labels that status bar will get filled up quickly which is why it does not do so by default.
The Elements in the Statusbar have a bunch of classes from Tiny Editor, you can examine it in the browser (chrome or firefox) with f12.
From there, it is no problem to override the current styling with some code like
.mce-statusbar.mce-container {
position : relative;
height : 0;
margin-top : -20px;
opacity : 0.5;
background-color :#fff;
border : 1px solid #333;
}
Beside, you can manipulate the code, where content is written in the Statusbar. See Plugin Wordcount for example. They are using some code like this to update the statusbar and enter a class name:
if (statusbar) {
Delay.setEditorTimeout(editor, function () {
statusbar.insert({
type: 'label',
name: 'wordcount',
text: ['Words: {0}', getCount()],
classes: 'wordcount',
disabled: editor.settings.readonly
}, 0);
editor.on('setcontent beforeaddundo undo redo keyup', debouncedUpdate);
}, 0);
}

Mat-select panel min-width

I'm trying to customize mat-select with multiple checkboxes.
for some reason the panel get wrong min-width as below:
and I don't know where its calculating this min-width.
also I tried to add panelClass and override the min-width from this class,
for example:
<mat-select #multipleSelect (selectionChange)="selectItem($event.value)" panelClass="multiple-panel" multiple>
&.multiple-panel {
min-width: 200px !important;
}
but when opening the dropdown its open with the original width (like in the pic) and after few millisecond"jump" to the custom min-width defined on the panel class.
I find the mat-select very hard to style. anybody knows how to solve this problem?
You can style your mat-select dialog box by giving a panel class (as you mentioned).
Please follow this demo : https://stackblitz.com/edit/angular-matselect-style?file=src/styles.css
to see the styled mat-select components.
Reason :
Reason for the delay is that angular for dialog-boxes, create a cdk-overlay-pane inside the cdk-overlay-container container, So in case of mat-select it provides a min-width of 180px, which is overridden by our panel class in the slight delay.
Yes, there is a slight delay in opening of dialog box and customizing its width to the specified width provided in the panel class. But the delay is acceptable in the project that i was working on. So, you can find the demo for styling the mat-select component, as i have provided 2 components and you can modify any css properties.
Try to use styles using ::ng-deep or :host >>>, if not finding any luck, please paste the styles in style.css.
Update 1 :
Tried css animations, and opacity for making smooth opening of the mat-select options.
.panel-class-applied-on-mat-select {
animation-name: opacityDelay !important;
animation-duration: 0.3s !important;
}
#keyframes opacityDelay {
0% {opacity: 0;}
25% {opacity: 0;}
50% {opacity: 0;}
75% {opacity: 0;}
100% {opacity: 1;}
}
Updated StackBlitz Demo
I used another approach.
Just added this piece of code to global style.
.mat-select-panel {
// some your code
&.ng-animating {
visibility: hidden;
}
}
You can try this solution on
DEMO StackBlitz.
Hack with opacity did not fix jumping width when select is closing.
You'll need to change viewEncapsulation to none at your component decorator.and then add following css to remove the transition effect.Have a look at viewencapsulation in angular docs https://angular.io/guide/component-styles#view-encapsulation.
#Component({
selector: 'app-selector',
templateUrl: './template.html',
styleUrls: ['./template.css'],
encapsulation: ViewEncapsulation.None
})
//CSS
.cdk-overlay-connected-position-bounding-box .cdk-overlay-pane .mat-select-panel.ng-animating {
display: none;
}
Try this way : define a panel class for your mat-select in the code and then in the global/app styling file just add:
.panel-class-name .mat-select-panel {
// add your styling here
}
It worked for me to add some component specific styling for material components.
Please go easy on me S.O. This is my first time contributing. :)
After debugging the console, and running into this issue. Solutions were not clear online. So I'm posting mine here in case someone else runs into this.
I found that there is a width permanently set for the infix class. If you unset it, and optionally add some padding to the right of the value, you'll find that will resolve the issue. Add :host for encapsulation when using ::ng-deep.
Important to Note: ::ng-deep is being permanently deprecated after Angular v14.
There is a property in the #Component() annotation called encapsulation which can be used to turn off the view encapsulation for the component instead of using ::ng-deep.
Solution for the deprecation of ::ng-deep:
#Component({
selector: 'app-selector-name',
template: `<div>Hello World!</div>`,
encapsulation: ViewEncapsulation.None,
styles: [
`
:host mat-form-field .mat-form-field-infix {
width: unset;
}
:host mat-form-field .mat-select-value {
padding-right: 0.5rem; /* 8px */
/* Alternatively, for TailwindCSS: #apply pr-2 */
}
:host .random-class {
/* some encapsulated styling... */
}
.another-random-class {
/* some non-encapsulated styling... */
}
`
]
})
Solution if you do not care about the deprecation of ::ng-deep:
:host ::ng-deep mat-form-field .mat-form-field-infix {
width: unset;
}
:host ::ng-deep mat-form-field .mat-select-value {
padding-right: 0.5rem; /* 8px */
}

Styling Panels of a Firefox Addon

So I created a Widget that the user clicks on and it opens up a Panel, I have a couple of Questions about the panel.
How Do I style the Panels borders, background color, etc..? I'm including an HTML file in it's contentURL, can I add CSS to alter it? If so how do I select it via CSS?
I also want to add a Close Button and keep the panel open always unless they click the close button.
On second thought, for the Add-on i'm trying to program it might be better if I make a window, is a window pretty stylable so I can make it look cooler?
Thanks for any help.
I don't think you can style panel borders. The panel border styles depend on the operating system and you cannot touch them. You can only really influence the inner area of the panel, effectively you get an iframe inside the panel that you can play with. E.g. to change the background your panel can contain:
<style type="text/css">
html
{
background-color: red;
}
</style>
You cannot, the panel is not a real HTML object, but a XUL window with an iframe or HTML inside.
I believe since Firefox 30 you can access to this object, you can read:
Avoid panel to autoHide in Firefox extension
Of course it's a kind of hack, looks like Mozilla is not really "open" ^^
I was able to modify the border of the panel:
/*run this first*/
var win = Services.wm.getMostRecentWindow('navigator:browser');
var panel = win.document.createElement('panel');
var screen = Services.appShell.hiddenDOMWindow.screen;
var props = {
noautohide: true,
noautofocus: false,
level: 'top',
style: 'padding:15px; margin:0; width:150px; height:200px; background-color:steelblue;border-radius:15px'
}
for (var p in props) {
panel.setAttribute(p, props[p]);
}
win.document.querySelector('#mainPopupSet').appendChild(panel);
panel.addEventListener('dblclick', function () {
panel.parentNode.removeChild(panel)
}, false);
panel.openPopup(null, 'overlap', screen.availLeft, screen.availTop);
So if you know the panel of your id just do this:
var sss = Cc['#mozilla.org/content/style-sheet-service;1'].getService(Ci.nsIStyleSheetService);
var css = '';
css += '#YourPanelIdHere { border-radius:15px; opacity:.5; border:1px solid red; }';
var cssEnc = encodeURIComponent(css);
var newURIParam = {
aURL: 'data:text/css,' + cssEnc,
aOriginCharset: null,
aBaseURI: null
}
var cssUri = Services.io.newURI(newURIParam.aURL, newURIParam.aOriginCharset, newURIParam.aBaseURI);
sss.loadAndRegisterSheet(cssUri, sss.USER_SHEET);
//sss.unregisterSheet(cssUri, sss.USER_SHEET);
That will style your panel. You don't have to use panel id in the style sheet, just anything that target your panel will do.

How to remove rounded corners from one jQuery UI widget but not the others?

My particular problem is that I want the autocomplete function to not have round corners, but all the other widgets that have round corners should.
Is there a parameter I can pass to disable the corners just for the autocomplete?
Edit
Let's see if this can be answered.
On page Datepicker.
I'd like to remove all round-corner classes from appearing (the header and the next-previous buttons).
$( "#datepicker" ).datepicker('widget').removeClass('ui-corner-all'); would not work.
Very late but here it goes:
jQuery UI widgets have a method, which returns the HTML node for the widget itself.
So the answer would be:
$('#someinput').autocomplete(...).autocomplete('widget').removeClass('ui-corner-all');
Responding to the EDIT:
As far I can see, you need to chain widget() method with autocomplete() (or datepicker()) method for it to work. Seems like it doesn't work for regular HTML nodes returned by $().
assign this css class to the element with corners of your widget.
.ui-corner-flat {
border-top-left-radius: 0px !important;
border-top-right-radius: 0px !important;
border-bottom-left-radius: 0px !important;
border-bottom-right-radius: 0px !important;
}
$("#elementwithcorners").addClass("ui-corner-flat");
to remove the bottom left radius
in the constructor I did this
$( "#signup" ).dialog(
{
create: function (event, ui) {
$(".ui-dialog").css('border-bottom-left-radius','0px');
},
}
);
The _suggest() method of the Autocomplete widget calls menu.refresh(), and therefore resets the ui-corner-all class for menu items, etc., each time the input changes. However, the open() callback is called after every menu.refresh() call within _suggest(), and so is a sensible place to adjust classes as desired:
$("#autocomplete").autocomplete("option", {
open: function(event, ui) {
$(this).autocomplete("widget")
.menu("widget").removeClass("ui-corner-all")
.find(".ui-corner-all").removeClass("ui-corner-all");
}
});
The Datepicker widget is a little tougher, as it's built to be sort of a semi-singleton. Here we need a monkey patch to do it consistently, since none of the supplied callback options is suitable:
// store the built-in update method on the "global" instance...
$.datepicker.__updateDatepicker = $.datepicker._updateDatepicker;
// ...and then clobber with our fix
$.datepicker._updateDatepicker = function(inst) {
$.datepicker.__updateDatepicker(inst);
inst.dpDiv.removeClass("ui-corner-all")
.find(".ui-corner-all").removeClass("ui-corner-all");
};
Note that the default _updateDatepicker() implementation has no return value. Also, note that the _updateDatepicker() method is not an interface method, so should not be assumed to be available. As such, the most consistent way to accomplish the corner fix is with appropriate CSS, along the lines of:
.ui-autocomplete.ui-menu.ui-corner-all,
.ui-autocomplete.ui-menu .ui-menu-item > a.ui-corner-all,
.ui-datepicker.ui-corner-all,
.ui-datepicker-header.ui-corner-all,
.ui-datepicker-next.ui-corner-all,
.ui-datepicker-prev.ui-corner-all {
border-radius: 0;
}
More specificity (or the !important directive) may be used to ensure these selectors are respected. This is exactly why jQuery uses theme classes – fudging these things in is an interesting hack, but it's the less clean option unless style is unavailable…
Create a new CSS class for the element you don't want rounded corners.
p.rounded { border-radius: 10px; }
p.none-rounded { border-radius: 0; }

With jQuery, how can I gray out and disable a webpage and then show some kind of spinner on top of that?

I am still pretty "green" when it comes to web development and javascript/jQuery programming, so any help is appreciated. Here is what I want to do.
I want to do the same thing that a jQuery UI dialog box does where it puts a semi-transparent image over the entire page and disables clicking of any of the controls underneath.
I want to know how I might put some kind of spinner overlay on top to show that the website is working in the background. If I can use a animated GIF file that would be fine, but I'm not quite sure on the best approach to this.
Here is an example of the grayed-out effect with a dialog box:
jQuery UI Example. I want to know how to produce this effect without the dialog box on top. I do not have a good example of the spinner behavior.
All suggestions, website referrals, and code is appreciated.
EDIT: I do not mean a "spinner control". I will try to find an example of what I am thinking of by spinner.
EDIT: What I mean by "spinner" is a loading gif of some kind like the "Indicator Big" gif on this website: http://ajaxload.info/
I always like to use the jQuery BlockUI plugin:
http://malsup.com/jquery/block/
Check out the demos, you'll probably find something you're looking for there.
One way to do it is to have a div that is hidden by default and has properties to set the background colour to a grey (#666 for instance) and its transparency set to something like 0.8.
When you want to display use jQuery to get the size of the screen/browser window, set the size of your div and display it with a high zindex, so it displays on top. You can also give this div your spinner gif graphic (no repeat, and centered).
Code:
#json-overlay {
background-color: #333;
opacity: 0.8;
position: absolute;
left: 0px;
top: 0px;
z-index: 100;
height: 100%;
width: 100%;
overflow: hidden;
background-image: url('ajax-loader.gif');
background-position: center;
background-repeat: no-repeat;
}
Only things to watch out for are select elements in IE6, as these will show through the div, so you can either use jQuery bgframe to solve that, or what I have done in the past is just hide select elements when displaying the div and showing them again when hiding your div
Why don't you just use "modal:true"?
$(function () {
$("#dialog").dialog($.extend({}, dialogOptions, {
autoOpen: false,
width: 500,
modal: true,
show: {
effect: "blind",
duration: 1000
},
hide: {
effect: "fade",
duration: 1000
}
}));
$("#profile_edit").click(function () {
$("#dialog").dialog("open");
});
$("#save_and_close").click(function () {
$("#dialog").dialog("close");
});
});
You can use something like this jquery code. Pass the id of the element that you want to stay on top of the page:
function startModal(id) {
$("body").prepend("<div id='PopupMask' style='position:fixed;width:100%;height:100%;z-index:10;background-color:gray;'></div>");
$("#PopupMask").css('opacity', 0.5);
$("#"+id).data('saveZindex', $("#"+id).css( "z-index"));
$("#"+id).data('savePosition', $("#"+id).css( "position"));
$("#"+id).css( "z-index" , 11 );
$("#"+id).css( "position" , "fixed" );
}
function stopModal(id) {
if ($("#PopupMask") == null) return;
$("#PopupMask").remove();
$("#"+id).css( "z-index" , $("#"+id).data('saveZindex') );
$("#"+id).css( "position" , $("#"+id).data('savePosition') );
}
you can use simple div and then ajaxstart and ajaxstop event
<div id="cover"></div>
$('#cover')
.hide()
.ajaxStart(function () {
$(this).fadeIn(100);
})
.ajaxStop(function () {
$(this).fadeOut(100);
});

Resources