Add Font Awesome to Kentico 8.2 CkEditor - ckeditor

I'm trying to add font-awesome to kentico 8.2 ckeditor (v4.4.0).
After adding the relevant versions of fontawesome and it's dependancies, the widget plugin throws the following error: Uncaught TypeError: CKEDITOR.style.addCustomHandler is not a function at plugin.js line 3200:
//
// WIDGET STYLE HANDLER ---------------------------------------------------
//
( function() {
/**
* The class representing a widget style. It is an {#link CKEDITOR#STYLE_OBJECT object} like
* the styles handler for widgets.
*
* **Note:** This custom style handler does not support all methods of the {#link CKEDITOR.style} class.
* Not supported methods: {#link #applyToRange}, {#link #removeFromRange}, {#link #applyToObject}.
*
* #since 4.4
* #class CKEDITOR.style.customHandlers.widget
* #extends CKEDITOR.style
*/
CKEDITOR.style.addCustomHandler( {
type: 'widget',
CkEditor do not support bug reporting for older versions so I'm wondering if anyone else here has come across this problem before?
Thanks in advance

Related

Styled component theme variable organization

This may not be the best place to post this so please let me know if this should be posted elsewhere.
I currently am trying to organize my applications theme, since it has become a bit messy. I was looking to see how other developers were organizing their app's theme. We have color/padding variables for our app's theme and overrides for our organization's component library we use. I was thinking of organizing the theme file some thing like this, but feel it may not be sustainable:
// colors
const white = '#FFFFFF'
const black = '#333333'
...
const grey100 = '#F8F8F8'
...
const grey600 = '#94969A'
/**
* App Specific Components
*/
const consumerTheme = {
// Issue I'm not sure if I should separate the general items such as
// component/title into different objects and if I should also separate
// padding/margin and colors
component1: {
background: white,
footerPadding: 5px
},
title: black,
...
}
/**
* Component Library Specific Components
*/
const componentLibrary = {
// Feeling uncertain if these values should be used throughout the app.
// The main idea here is that even if we don't see these values
// throughout the app's codebase, these values are overriding our
// component library default values.
header: {
background: white,
},
error: '#C63527'
...
}

Broken styles with amcharts4

I'm trying to import amcharts' parts in the vue component like that:
import * as am4core from "#amcharts/amcharts4/core";
import * as am4charts from "#amcharts/amcharts4/charts";
but it breaks styles of the site: final css file contains only /* (ignored) *//* (ignored) *//* (ignored) */ instead of the actual styles. I've found a thread on the github with the same problem, but it was close w/o any resolution.
Could anyone help me to figure out the reason of this behavior and the actual fix?
amcharts: 4.10.5; Webpack: 4.43.0
So, I've found a solution for this.
You need to remove those generated files (if they were created):
public/vendors~xlsx.js
public/xlsx.js
public/vendors~pdfmake.js
public/vendors~canvg.js
Add this to the webpack configuration (for laravel-mix add this inside the mix.webpackConfig({...}) construction):
{
externals: function (context, request, callback) {
if (/xlsx|canvg|pdfmake/.test(request)) {
return callback(null, "commonjs " + request);
}
callback();
}
}
More details are here.

How can I disable drop events in CKEditor 5

we are trying to implement CKEditor 5 into our apps and we are struggling a bit with docs.
We want to disable drop event into an editing area or control it somehow. Is there an event for that?
We were trying editor.model.document.on('clipboardInput') or editor.model.document.on('dragover') without any luck. These events are not fired.
You need to listen to the dragover and drop events on the view layer instead of on the model.
I prepared a simple function that can be loaded as a plugin to CKEditor 5 which cancels these events:
/**
* Cancel the `drop` and `dragover` events.
*
* #param {module:core/editor/editor~Editor} editor
*/
function cancelDropEvents( editor ) {
// High priority means that the callbacks below will be called before other CKEditor's plugins.
editor.editing.view.document.on( 'drop', ( evt, data ) => {
// Stop executing next callbacks.
evt.stop();
// Prevent the default event action.
data.preventDefault();
}, { priority: 'high' } );
editor.editing.view.document.on( 'dragover', ( evt, data ) => {
evt.stop();
data.preventDefault();
}, { priority: 'high' } );
}
You can check how it works online – https://jsfiddle.net/pomek/qz0o9ku0/.

Firefox Extension, Window related sidebar

I'm writing an extension for Firefox, and I need the UI of this extension to be on a sidebar, I followed some mozilla tutorials, but sidebars are not related to just one window.
I need a sidebar like UI, that will save navigation data from the same window, and need it to be related to just that window, something like firebug.
What I did so far is just creating a menu, and an item, I need that a click on this item will toggle my sidebar.
I took a look at firebug source, I didn't find any overlay of sidebar in its XUL, the scripts are complicated for me, so i didn't know how they can add their UI to the window.
Any ideas, or sources I can read about this ?
When talking about a Sidebar one needs to be careful about terminology. The specific term that Mozilla uses within Firefox for "Sidebar" refers to a content box that is on the side of the UI. The Sidebar, if open, is a constant part of the UI which is shown independent of the tab selected. Only one is provided for which can be chosen to be on the left or the right. It is routinely used for content that does not change from tab to tab (e.g. Bookmarks, or History).
The UI that is used for the Firefox devtools (and placement was adopted for use by FireBug) is a sub-panel within the current tab. It is shown only within the tab in which it was invoked. It is implemented within an <iframe>. It can also be opened as a separate window.
When you have a known working example, one way to figure out how this type of thing is implemented in the DOM (the entire browser window is a DOM) is to install the add-on DOM Inspector and use it to investigate what the contents of the DOM looks like. You probably also want, the Element Inspector add-on which is a very useful addition to the DOM Inspector (shift-right-click opens the DOM Inspector to the element clicked). You might also find Stacked Inspector helpful.
Another way to figure out how it is being done is to look at the source code. For the devtools the interface is actually created in the function SH_create within resource:///modules/devtools/framework/toolbox-hosts.js
When placed at the bottom location, the UI is placed as a child of the <notificationbox> which exists for each tab. You can find the <notificationbox> for a tab by using the gBrowser.getNotificationBox( browserForTab ) method. The elements inserted are a <splitter> and an <iframe>. When placed in the other locations within the browser tab those two elements are inserted at locations in the Browser DOM either as children of the <notificationbox>, or as children of its child <hbox> that has class="browserSidebarContainer".
As an example, the following functions will, depending on the [location] parameter, create a panel on the left, right, top, or bottom of the current tab or as a separate window. The default is that the panel is composed of an <iframe> separated from the browser content by a <splitter>. The createInterfacePanel() function is more generic and will accept any element or DOM object as the second parameter which is inserted into the DOM at the appropriate place based on [location] and separated by a form the content. Such Object is expect to be either a Document Fragment or element.
/**
* Creates an <iframe> based panel within the current tab,
* or opens a window, for use as an user interface box.
* If it is not a window, it is associated with the current
* browser tab.
* #param location
* Placement of the panel [right|left|top|bottom|window]
* The default location is "right".
* #param size
* Width if on left or right. Height if top or bottom.
* Both width and height if location="window" unless
* features is a string.
* Default is 400.
* #param id
* The ID to assign to the iframe. Default is
* "makyen-interface-panel"
* The <splitter> will be assigned the
* ID = id + "-splitter"
* #param chromeUrl
* This is the chrome:// URL to use for the contents
* of the iframe or the window.
* the default is:
* "chrome://browser/content/devtools/framework/toolbox.xul"
* #param features
* The features string for the window. See:
* https://developer.mozilla.org/en-US/docs/Web/API/Window.open
* returns [splitterEl, iframeEl]
* The elements for the <splitter> and <iframe>
*
* Copyright 2014 by Makyen.
* Released under the MPL 2.0. http://mozilla.org/MPL/2.0/.
**/
function createInterfacePanelIframe(location,size,id,chromeUrl,features) {
//defaults
size = ( (typeof size !== "number") || size<1) ? 400 : size;
id = typeof id !== "string" ? "makyen-interface-panel" : id;
chromeUrl = typeof chromeUrl !== "string"
? "chrome://browser/content/devtools/framework/toolbox.xul"
: chromeUrl;
//Create some common variables if they do not exist.
// This should work from any Firefox context.
// Depending on the context in which the function is being run,
// this could be simplified.
if (typeof window === "undefined") {
//If there is no window defined, get the most recent.
var window=Components.classes["#mozilla.org/appshell/window-mediator;1"]
.getService(Components.interfaces.nsIWindowMediator)
.getMostRecentWindow("navigator:browser");
}
if (typeof document === "undefined") {
//If there is no document defined, get it
var document = window.content.document;
}
if (typeof gBrowser === "undefined") {
//If there is no gBrowser defined, get it
var gBrowser = window.gBrowser;
}
//Get the current tab & notification box (container for tab UI).
let tab = gBrowser.selectedTab;
let browserForTab = gBrowser.getBrowserForTab( tab );
let notificationBox = gBrowser.getNotificationBox( browserForTab );
let ownerDocument = gBrowser.ownerDocument;
//Create the <iframe> use
//ownerDocument for the XUL namespace.
let iframeEl = ownerDocument.createElement("iframe");
iframeEl.id = id;
iframeEl.setAttribute("src",chromeUrl);
iframeEl.setAttribute("height", size.toString());
iframeEl.setAttribute("width", size.toString());
//Call createInterfacePanel, pass the size if it is to be a window.
let splitterEl;
if(location == "window" ) {
splitterEl = createInterfacePanel(location, size, size
,id + "-splitter", chromeUrl, features);
return [splitterEl, null];
} else {
splitterEl = createInterfacePanel(location, iframeEl, iframeEl
,id + "-splitter", chromeUrl, features);
}
return [splitterEl, iframeEl];
}
/**
* Creates a panel within the current tab, or opens a window, for use as a
* user interface box. If not a window, it is associated with the current
* browser tab.
* #param location
* Placement of the panel [right|left|top|bottom|window]
* The default location is "right".
* #param objectEl
* The element of an XUL object that will be inserted into
* the DOM such that it is within the current tab.
* Some examples of possible objects are <iframe>,
* <browser>, <box>, <hbox>, <vbox>, etc.
* If the location="window" and features is not a string
* and this is a number then it is used as the width of the
* window.
* If features is a string, it is assumed the width is
* set in that, or elsewhere (e.g. in the XUL).
* #param sizeEl
* The element that contains attributes of "width" and
* "height". If location=="left"|"right" then the
* "height" attribute is removed prior to the objectEl
* being inserted into the DOM.
* A spearate reference for the size element in case the
* objectEl is a documentFragment containing multiple elements.
* However, normal usage is for objectEl === sizeEl when
* location != "window".
* When location == "window" and features is not a string,
* and sizeEl is a number then it is used as the height
* of the window.
* If features is a string, it is assumed the height is
* set in that, or elsewhere (e.g. in the XUL).
* #param id
* The ID to assign to the <splitter>. The default is:
* "makyen-interface-panel-splitter".
* #param chromeUrl
* This is the chrome:// URL to use for the contents
* of the window.
* the default is:
* "chrome://browser/content/devtools/framework/toolbox.xul"
* #param features
* The features string for the window. See:
* https://developer.mozilla.org/en-US/docs/Web/API/Window.open
* returns
* if location != "window":
* splitterEl, The element for the <splitter>.
* if location == "window":
* The windowObjectReference returned by window.open().
*
* Copyright 2014 by Makyen.
* Released under the MPL 2.0. http://mozilla.org/MPL/2.0/.
**/
function createInterfacePanel(location,objectEl,sizeEl,id,chromeUrl,features) {
//Set location default:
location = typeof location !== "string" ? "right" : location;
if(location == "window") {
if(typeof features !== "string") {
let width = "";
let height = "";
if(typeof objectEl == "number") {
width = "width=" + objectEl.toString() + ",";
}
if(typeof sizeEl == "number") {
height = "height=" + sizeEl.toString() + ",";
}
features = width + height
+ "menubar=no,toolbar=no,location=no,personalbar=no"
+ ",status=no,chrome=yes,resizable,centerscreen";
}
}
id = typeof id !== "string" ? "makyen-interface-panel-splitter" : id;
chromeUrl = typeof chromeUrl !== "string"
? "chrome://browser/content/devtools/framework/toolbox.xul"
: chromeUrl;
//Create some common variables if they do not exist.
// This should work from any Firefox context.
// Depending on the context in which the function is being run,
// this could be simplified.
if (typeof window === "undefined") {
//If there is no window defined, get the most recent.
var window=Components.classes["#mozilla.org/appshell/window-mediator;1"]
.getService(Components.interfaces.nsIWindowMediator)
.getMostRecentWindow("navigator:browser");
}
if (typeof document === "undefined") {
//If there is no document defined, get it
var document = window.content.document;
}
if (typeof gBrowser === "undefined") {
//If there is no gBrowser defined, get it
var gBrowser = window.gBrowser;
}
//Get the current tab & notification box (container for tab UI).
let tab = gBrowser.selectedTab;
let browserForTab = gBrowser.getBrowserForTab( tab );
let notificationBox = gBrowser.getNotificationBox( browserForTab );
let ownerDocument = gBrowser.ownerDocument;
//Create a Document Fragment.
//If doing multiple DOM additions, we should be in the habit
// of doing things in a way which causes the least number of reflows.
// We know that we are going to add more than one thing, so use a
// document fragment.
let docFrag = ownerDocument.createDocumentFragment();
//ownerDocument must be used here in order to have the XUL namespace
// or the splitter causes problems.
// createElementNS() does not work here.
let splitterEl = ownerDocument.createElement("splitter");
splitterEl.id = id ;
//Look for the child element with class="browserSidebarContainer".
//It is the element in procimity to which the <splitter>
//and objectEl will be placed.
let theChild = notificationBox.firstChild;
while (!theChild.hasAttribute("class")
|| !theChild.getAttribute("class").contains("browserSidebarContainer")
) {
theChild = theChild.nextSibling;
if(!theChild) {
//We failed to find the correct node.
//This implies that the structure Firefox
// uses has changed significantly and it should
// be assumed that the extension is no longer compatible.
return null;
}
}
let toReturn = null;
switch(location) {
case "window" :
return window.open(chromeUrl,"_blank",features);
break;
case "top" :
if(sizeEl) {
sizeEl.removeAttribute("width");
}
docFrag.appendChild(objectEl);
docFrag.appendChild(splitterEl);
//Inserting the document fragment results in the same
// DOM structure as if you Inserted each child of the
// fragment separately. (i.e. the document fragment
// is just a temporary container).
//Insert the interface prior to theChild.
toReturn = notificationBox.insertBefore(docFrag,theChild);
break;
case "bottom" :
if(sizeEl) {
sizeEl.removeAttribute("width");
}
docFrag.appendChild(splitterEl);
docFrag.appendChild(objectEl);
//Insert the interface just after theChild.
toReturn = notificationBox.insertBefore(docFrag,theChild.nextSibling);
break;
case "left" :
if(sizeEl) {
sizeEl.removeAttribute("height");
}
docFrag.appendChild(objectEl);
//Splitter is second in this orientaiton.
docFrag.appendChild(splitterEl);
//Insert the interface as the first child of theChild.
toReturn = theChild.insertBefore(docFrag,theChild.firstChild);
break;
case "right" :
default :
//Right orientaiton, the default.
if(sizeEl) {
sizeEl.removeAttribute("height");
}
docFrag.appendChild(splitterEl);
docFrag.appendChild(objectEl);
//Insert the interface as the last child of theChild.
toReturn = theChild.appendChild(docFrag);
break;
}
return splitterEl;
}
Update:
The code in this answer was significantly enhanced for my answer to "Firefox SDK Add-on with a sidebar on both the right and left at the same time". You are probably much better off using the code contained in that answer rather than the code found here.

why an addon for firefox is only avaliable though the view menu toolbar?

I've developed an add-on for Firefox and is installs ok in windows Firefox but in linux mint i must go to the View menu then toolbars and select personalize to put the created add-on button to the toolbar near my firebug (i mean where other add-ons coexist)
To put a toolbarbutton on the nav-bar automatically, it isn't enough to create the button. You have to add it to the "current set" of icons in the toolbar. If you don't do this, it will only be added to the
My guess is your code is not working on windows either. You may have added it to the toolbar manually some time ago and it is there since.(Try installing your addon in a blank profile).
To make it "persistent" automatically you can add it to the current set on the first time you run your addon, with the following:
/**
* Installs the toolbar button with the given ID into the given
* toolbar, if it is not already present in the document.
*
* #param {string} toolbarId The ID of the toolbar to install to.
* #param {string} id The ID of the button to install.
* #param {string} afterId The ID of the element to insert after. #optional
*/
function installButton(toolbarId, id, afterId) {
if (!document.getElementById(id)) {
var toolbar = document.getElementById(toolbarId);
// If no afterId is given, then append the item to the toolbar
var before = null;
if (afterId) {
let elem = document.getElementById(afterId);
if (elem && elem.parentNode == toolbar)
before = elem.nextElementSibling;
}
toolbar.insertItem(id, before);
toolbar.setAttribute("currentset", toolbar.currentSet);
document.persist(toolbar.id, "currentset");
if (toolbarId == "addon-bar")
toolbar.collapsed = false;
}
}
if (firstRun) {
installButton("nav-bar", "my-extension-navbar-button");
// The "addon-bar" is available since Firefox 4
installButton("addon-bar", "my-extension-addon-bar-button");
}
Reference: Toolbar - Code snippets

Resources