]> BookStack Code Mirror - bookstack/blobdiff - resources/js/components/pointer.js
Altered ldap_connect usage, cleaned up LDAP classes
[bookstack] / resources / js / components / pointer.js
index a74422ce4daba63d12a7bf701fef9663f1baab13..e2e2ceca729fd0d5952ece4c3b6eb09bd1657267 100644 (file)
@@ -1,13 +1,13 @@
-import * as DOM from "../services/dom";
-import Clipboard from "clipboard/dist/clipboard.min";
+import * as DOM from '../services/dom';
+import {Component} from './component';
+import {copyTextToClipboard} from '../services/clipboard';
 
-/**
- * @extends Component
- */
-class Pointer {
+export class Pointer extends Component {
 
     setup() {
         this.container = this.$el;
+        this.input = this.$refs.input;
+        this.button = this.$refs.button;
         this.pageId = this.$opts.pageId;
 
         // Instance variables
@@ -16,22 +16,18 @@ class Pointer {
         this.pointerModeLink = true;
         this.pointerSectionId = '';
 
-        this.init();
         this.setupListeners();
     }
 
-    init() {
-        // Set up pointer by removing it
-        this.container.parentNode.removeChild(this.container);
-
-        // Set up clipboard
-        new Clipboard(this.container.querySelector('button'));
-    }
-
     setupListeners() {
+        // Copy on copy button click
+        this.button.addEventListener('click', () => {
+            copyTextToClipboard(this.input.value);
+        });
+
         // Select all contents on input click
-        DOM.onChildEvent(this.container, 'input', 'click', (event, input) => {
-            input.select();
+        this.input.addEventListener('click', event => {
+            this.input.select();
             event.stopPropagation();
         });
 
@@ -50,10 +46,9 @@ class Pointer {
         });
 
         // Hide pointer when clicking away
-        DOM.onEvents(document.body, ['click', 'focus'], event => {
+        DOM.onEvents(document.body, ['click', 'focus'], () => {
             if (!this.showing || this.isSelection) return;
-            this.container.parentElement.removeChild(this.container);
-            this.showing = false;
+            this.hidePointer();
         });
 
         // Show pointer when selecting a single block of tagged content
@@ -67,6 +62,11 @@ class Pointer {
         });
     }
 
+    hidePointer() {
+        this.container.style.display = null;
+        this.showing = false;
+    }
+
     /**
      * Move and display the pointer at the given element, targeting the given screen x-position if possible.
      * @param {Element} element
@@ -80,23 +80,29 @@ class Pointer {
         this.pointerSectionId = element.id;
         this.updateForTarget(element);
 
-        element.parentNode.insertBefore(this.container, element);
         this.container.style.display = 'block';
+        const targetBounds = element.getBoundingClientRect();
+        const pointerBounds = this.container.getBoundingClientRect();
+
+        const xTarget = Math.min(Math.max(xPosition, targetBounds.left), targetBounds.right);
+        const xOffset = xTarget - (pointerBounds.width / 2);
+        const yOffset = (targetBounds.top - pointerBounds.height) - 16;
+
+        this.container.style.left = `${xOffset}px`;
+        this.container.style.top = `${yOffset}px`;
+
         this.showing = true;
         this.isSelection = true;
 
-        // Set pointer to sit near mouse-up position
-        requestAnimationFrame(() => {
-            const bookMarkBounds = element.getBoundingClientRect();
-            const pointerLeftOffset = Math.max((xPosition - bookMarkBounds.left - 164), 0);
-            const pointerLeftOffsetPercent = (pointerLeftOffset / bookMarkBounds.width) * 100;
-
-            this.container.children[0].style.left = pointerLeftOffsetPercent + '%';
+        setTimeout(() => {
+            this.isSelection = false;
+        }, 100);
 
-            setTimeout(() => {
-                this.isSelection = false;
-            }, 100);
-        });
+        const scrollListener = () => {
+            this.hidePointer();
+            window.removeEventListener('scroll', scrollListener, {passive: true});
+        };
+        window.addEventListener('scroll', scrollListener, {passive: true});
     }
 
     /**
@@ -106,15 +112,15 @@ class Pointer {
     updateForTarget(element) {
         let inputText = this.pointerModeLink ? window.baseUrl(`/link/${this.pageId}#${this.pointerSectionId}`) : `{{@${this.pageId}#${this.pointerSectionId}}}`;
         if (this.pointerModeLink && !inputText.startsWith('http')) {
-            inputText = window.location.protocol + "//" + window.location.host + inputText;
+            inputText = `${window.location.protocol}//${window.location.host}${inputText}`;
         }
 
-        this.container.querySelector('input').value = inputText;
+        this.input.value = inputText;
 
         // Update anchor if present
         const editAnchor = this.container.querySelector('#pointer-edit');
         if (editAnchor && element) {
-            const editHref = editAnchor.dataset.editHref;
+            const {editHref} = editAnchor.dataset;
             const elementId = element.id;
 
             // get the first 50 characters.
@@ -122,6 +128,5 @@ class Pointer {
             editAnchor.href = `${editHref}?content-id=${elementId}&content-text=${encodeURIComponent(queryContent)}`;
         }
     }
-}
 
-export default Pointer;
\ No newline at end of file
+}