Skip to content

Commit

Permalink
Adds shadow dom support slab#2021
Browse files Browse the repository at this point in the history
  • Loading branch information
Peter Soots committed May 31, 2018
1 parent 223db76 commit 1cee540
Show file tree
Hide file tree
Showing 6 changed files with 105 additions and 16 deletions.
20 changes: 12 additions & 8 deletions core/emitter.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,23 +5,27 @@ let debug = logger('quill:events');

const EVENTS = ['selectionchange', 'mousedown', 'mouseup', 'click'];

EVENTS.forEach(function(eventName) {
document.addEventListener(eventName, (...args) => {
[].slice.call(document.querySelectorAll('.ql-container')).forEach((node) => {
// TODO use WeakMap
if (node.__quill && node.__quill.emitter) {
node.__quill.emitter.handleDOM(...args);
function registerDOMListeners (dom) {
EVENTS.forEach(function(eventName) {
dom.addEventListener(eventName, (...args) => {
if (dom.__quill && dom.__quill.emitter) {
dom.__quill.emitter.handleDOM(...args);
}
});
});
});
}


class Emitter extends EventEmitter {
constructor() {
constructor(dom = null) {
super();
this.listeners = {};
this.on('error', debug.error);
this.dom = dom

if (this.dom) {
registerDOMListeners(this.dom)
}
}

emit() {
Expand Down
2 changes: 1 addition & 1 deletion core/quill.js
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ class Quill {
this.root.classList.add('ql-blank');
this.root.setAttribute('data-gramm', false);
this.scrollingContainer = this.options.scrollingContainer || this.root;
this.emitter = new Emitter();
this.emitter = new Emitter(this.container);
this.scroll = Parchment.create(this.root, {
emitter: this.emitter,
whitelist: this.options.formats
Expand Down
31 changes: 25 additions & 6 deletions core/selection.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,12 +22,13 @@ class Selection {
this.composing = false;
this.mouseDown = false;
this.root = this.scroll.domNode;
this.domRoot = this.getDomRoot(this.root);
this.cursor = Parchment.create('cursor', this);
// savedRange is last non-null range
this.lastRange = this.savedRange = new Range(0, 0);
this.handleComposition();
this.handleDragging();
this.emitter.listenDOM('selectionchange', document, () => {
this.emitter.listenDOM('selectionchange', this.root, () => {
if (!this.mouseDown) {
setTimeout(this.update.bind(this, Emitter.sources.USER), 1);
}
Expand Down Expand Up @@ -75,10 +76,10 @@ class Selection {
}

handleDragging() {
this.emitter.listenDOM('mousedown', document.body, () => {
this.emitter.listenDOM('mousedown', this.root, () => {
this.mouseDown = true;
});
this.emitter.listenDOM('mouseup', document.body, () => {
this.emitter.listenDOM('mouseup', this.root, () => {
this.mouseDown = false;
this.update(Emitter.sources.USER);
});
Expand Down Expand Up @@ -156,8 +157,26 @@ class Selection {
}
}

getDomRoot(ctx) {
if (ctx === document) {
return ctx
}
if (HTMLElement.prototype.attachShadow) {
if (ctx instanceof ShadowRoot) {

if (typeof ctx.getSelection === 'function') {
return ctx
}

return document
}
}

return this.getDomRoot(ctx.parentNode)
}

getNativeRange() {
let selection = document.getSelection();
let selection = this.domRoot.getSelection();
if (selection == null || selection.rangeCount <= 0) return null;
let nativeRange = selection.getRangeAt(0);
if (nativeRange == null) return null;
Expand All @@ -174,7 +193,7 @@ class Selection {
}

hasFocus() {
return document.activeElement === this.root;
return !!(this.domRoot.activeElement === this.root);
}

normalizedToRange(range) {
Expand Down Expand Up @@ -268,7 +287,7 @@ class Selection {
if (startNode != null && (this.root.parentNode == null || startNode.parentNode == null || endNode.parentNode == null)) {
return;
}
let selection = document.getSelection();
let selection = this.domRoot.getSelection();
if (selection == null) return;
if (startNode != null) {
if (!this.hasFocus()) this.root.focus();
Expand Down
59 changes: 59 additions & 0 deletions docs/_includes/standalone/shadow.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
<!-- head -->


<!-- head -->
<template id="shadow-contents">
<link rel="stylesheet" href="{{site.katex}}/katex.min.css">
<link rel="stylesheet" href="{{site.highlightjs}}/styles/monokai-sublime.min.css">
<link rel="stylesheet" href="{{site.cdn}}{{site.version}}/quill.snow.css">
<style>
.standalone-container {
margin: 50px auto;
max-width: 720px;
}
#snow-container {
height: 350px;
}
</style>
<div class="standalone-container">
<div id="snow-container"></div>
</div>
</template>
<p>I'm a text thing that's outside</p>
<quill-editor></quill-editor>

<!-- script -->
<script src="{{site.katex}}/katex.min.js"></script>
<script src="{{site.highlightjs}}/highlight.min.js"></script>
<script src="{{site.cdn}}{{site.version}}/{{site.quill}}"></script>
<script>
let shadowContents = document.getElementById('shadow-contents').innerHTML

class Editor extends HTMLElement {
constructor () {
super()
this.wrapper = this.createInnerDocument()
this.quill = this.createEditor()
}

createInnerDocument () {
let shadow = this.attachShadow({ mode: 'open' })
let shadowContainer = document.createElement('div')
shadowContainer.innerHTML = shadowContents
shadow.appendChild(shadowContainer)
return shadowContainer
}

createEditor () {
let container = this.wrapper.querySelector('#snow-container')
return new Quill(container, {
placeholder: 'Compose an epic...',
theme: 'snow'
})
}
}

window.customElements.define('quill-editor', Editor)

</script>
<!-- script -->
7 changes: 7 additions & 0 deletions docs/docs/standalone/shadow.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
layout: standalone
title: Snow Theme under Shadow DOM
permalink: /standalone/shadow/
---

{% include standalone/shadow.html %}
2 changes: 1 addition & 1 deletion test/helpers/unit.js
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@ function initialize(klass, html, container = this.container) {
}
if (klass === HTMLElement) return container;
if (klass === Quill) return new Quill(container);
let emitter = new Emitter();
let emitter = new Emitter(container);
let scroll = new Scroll(container, { emitter: emitter });
if (klass === Scroll) return scroll;
if (klass === Editor) return new Editor(scroll);
Expand Down

0 comments on commit 1cee540

Please sign in to comment.