Skip to content

Instantly share code, notes, and snippets.

@butsjoh
Last active March 26, 2022 12:21
Show Gist options
  • Save butsjoh/fbe4c824fef939f0911d to your computer and use it in GitHub Desktop.
Save butsjoh/fbe4c824fef939f0911d to your computer and use it in GitHub Desktop.
Quill popover toolbar (when performing a selection it will show)
var QuillExtend = function(child, parent) { for (var key in parent) { if ({}.hasOwnProperty.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; };
PopoverToolbar = (function(superClass) {
QuillExtend(PopoverToolbar, superClass);
var _ = Quill.require('lodash');
var dom = Quill.require('dom');
// lodash has debounce but quill is not adding it in his dist
var debounce = function debounce(fn, quietMillis, ctx) {
ctx = ctx || undefined;
var timeout;
return function () {
var args = arguments;
window.clearTimeout(timeout);
timeout = window.setTimeout(function() {
fn.apply(ctx, args);
}, quietMillis);
};
};
function PopoverToolbar(quill, options) {
PopoverToolbar.__super__.constructor.call(this, quill, options);
if (this.options.style == 'popover') {
dom(this.container).addClass('ql-toolbar-popover');
}
this.quill.on(this.quill.constructor.events.SELECTION_CHANGE, (function(_this) {
return function(range) {
return _this.setDisplayState(range);
};
})(this));
window.onresize = debounce(function(e) { this.setDisplayState(null); }, 100, this);
}
PopoverToolbar.prototype.hide = function() {
this.container.style.visibility = 'hidden';
};
PopoverToolbar.prototype.show = function() {
var coords = this._calculateToolbarPosition();
this.container.style.visibility = 'visible';
this.container.style.top = coords.top;
this.container.style.left = coords.left;
};
PopoverToolbar.prototype.setDisplayState = function(range) {
var range = range || this.quill.getSelection();
if (range && !range.isCollapsed()) {
this.show();
} else {
this.hide();
}
};
PopoverToolbar.prototype._calculateToolbarPosition = function() {
// position the toolbar at left 0, so we can get the real width of the toolbar
this.container.style.left = '0';
var toolbarBounds = this.container.getBoundingClientRect(),
halfOffsetWidth = toolbarBounds.width / 2,
toolbarBottomOffset = 0,
windowSize = window.innerWidth || document.documentElement.clientWidth,
containerBounds = this.quill.container.getBoundingClientRect(),
editorBounds = this.quill.root.getBoundingClientRect(),
leftOffset = editorBounds.left - containerBounds.left,
selection = this.quill.getSelection(),
boundsLeft = this.quill.getBounds(selection.start),
boundsRight = this.quill.getBounds(selection.end),
middleBoundary = (boundsLeft.left + boundsRight.left) / 2,
editorContainerTopOffset = editorBounds.top - containerBounds.top,
coords = {};
// Decide whether to display the toolbar at the bottom or the top depending on scroll position
if (((editorBounds.top) - this.options.fixedTopOffset - editorContainerTopOffset) + boundsLeft.top < (toolbarBounds.height + toolbarBottomOffset)) {
console.log('BOTTOM');
coords.top = ((boundsRight.top + boundsRight.height ) + toolbarBottomOffset ) + 'px';
} else {
console.log('TOP');
coords.top = (boundsLeft.top - toolbarBottomOffset - toolbarBounds.height) + 'px';
}
// Decide left position
if (editorBounds.left + middleBoundary < halfOffsetWidth) {
console.log('ALL LEFT');
coords.left = editorBounds.left + 'px';
} else if (editorBounds.right - editorBounds.left - middleBoundary < halfOffsetWidth || boundsRight.left == leftOffset) {
console.log('ALL RIGHT');
coords.left = (editorBounds.right - (editorBounds.left + toolbarBounds.width)) + 'px';
} else if (boundsLeft.top != boundsRight.top) {
console.log('MIDDLE EDITOR');
coords.left = ((editorBounds.width / 2) - halfOffsetWidth) + 'px';
} else {
console.log('MIDDLE');
coords.left = ((middleBoundary - halfOffsetWidth)) + 'px';
}
return coords;
};
return PopoverToolbar;
})(Quill.modules['toolbar']);
Quill.registerModule('popover-toolbar', PopoverToolbar);
// css of toolbar
.ql-toolbar-popover {
display: inline-block;
visibility: hidden;
position: absolute;
top: 0;
z-index: 10;
}
editor = new Quill('#editor-container', {
modules: {
'popover-toolbar': { container: '#formatting-container', style: 'popover', fixedTopOffset: 0}
}
);
@thomsbg
Copy link

thomsbg commented Mar 9, 2015

Thanks for sharing!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment