@samuelbradshaw/highlight-helper-js 0.7.5 → 0.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -101,6 +101,9 @@ Options can be provided when Highlight Helper is initialized. They can also be s
101
101
  - **defaultStyle** – Key of the default highlight style. Default: `fill`.
102
102
  - **defaultWrapper** – Key of the default highlight wrapper. Default: `none`.
103
103
  - **highlightIdFunction** – Identifier of a function that provides unique IDs for new highlights. Default: `hhGetNewHighlightId`.
104
+ - **showCustomSelectionHandlesForActiveHighlights** – Whether custom selection handles should show for active highlights. Default: `true`.
105
+ - **showCustomSelectionHandlesForTextSelection** – Whether custom selection handles should show for text selection. Default: `false`.
106
+ - **showCustomSelectionHandlesOnTouch** – Whether custom selection handles should show on touch devices. Default: `false`.
104
107
 
105
108
 
106
109
  ### <a name="custom-events"></a>Custom events
package/demo.html CHANGED
@@ -147,6 +147,12 @@
147
147
  <label><input type="radio" name="hh-drawing-mode" value="highlight-api"> Custom Highlight API</label><br>
148
148
  <label><input type="radio" name="hh-drawing-mode" value="mark-elements"> HTML mark elements</label><br>
149
149
  </p>
150
+ <p>
151
+ Show custom selection handles:<br>
152
+ <label><input type="checkbox" id="hh-selection-handles-active-highlights" checked> For active highlights</label><br>
153
+ <label><input type="checkbox" id="hh-selection-handles-text-selection"> For text selection</label><br>
154
+ <label><input type="checkbox" id="hh-selection-handles-touch"> On touch devices</label><br>
155
+ </p>
150
156
  <b>Active highlight:</b>
151
157
  <div id="snippet-container">
152
158
  <div id="snippet">N/A</div>
@@ -263,6 +269,12 @@
263
269
  }
264
270
  });
265
271
  }
272
+ const selectionHandlesActiveHighlightsCheckbox = document.getElementById('hh-selection-handles-active-highlights');
273
+ selectionHandlesActiveHighlightsCheckbox.addEventListener('change', (event) => { highlighter.setOption('showCustomSelectionHandlesForActiveHighlights', event.currentTarget.checked); });
274
+ const selectionHandlesTextSelectionCheckbox = document.getElementById('hh-selection-handles-text-selection');
275
+ selectionHandlesTextSelectionCheckbox.addEventListener('change', (event) => { highlighter.setOption('showCustomSelectionHandlesForTextSelection', event.currentTarget.checked); });
276
+ const selectionHandlesOnTouchCheckbox = document.getElementById('hh-selection-handles-touch');
277
+ selectionHandlesOnTouchCheckbox.addEventListener('change', (event) => { highlighter.setOption('showCustomSelectionHandlesOnTouch', event.currentTarget.checked); });
266
278
 
267
279
  const container = document.querySelector(highlighter.getOptions().containerSelector);
268
280
  const snippetDiv = document.getElementById('snippet');
@@ -70,6 +70,9 @@ function Highlighter(options = hhDefaultOptions) {
70
70
  width: 0px;
71
71
  visibility: hidden;
72
72
  }
73
+ [data-hh-pointer-down="true"] .hh-selection-handle {
74
+ visibility: hidden !important;
75
+ }
73
76
  .hh-selection-handle-content {
74
77
  position: absolute;
75
78
  height: 100%;
@@ -642,13 +645,13 @@ function Highlighter(options = hhDefaultOptions) {
642
645
  this.annotatableContainer.addEventListener('pointerdown', (event) => respondToPointerDown(event), { signal: controller.signal });
643
646
  const respondToPointerDown = (event) => {
644
647
  const isSecondaryClick = (event.button !== 0 || event.altKey || event.ctrlKey || event.metaKey || event.shiftKey);
648
+ if (!isSecondaryClick) this.annotatableContainer.dataset.hhPointerDown = 'true';
645
649
  pointerType = event.pointerType;
646
650
 
647
651
  // Pointer down on a selection handle
648
652
  if (event.target?.closest('.hh-selection-handle')) {
649
653
  if (!isSecondaryClick) {
650
654
  activeSelectionHandle = event.target.parentElement.closest('.hh-selection-handle');
651
- this.annotatableContainer.dataset.hhDragging = 'true';
652
655
  const selectionHandleClientRect = activeSelectionHandle.getBoundingClientRect();
653
656
  const lineHeight = selectionHandleClientRect.bottom - selectionHandleClientRect.top;
654
657
  activeSelectionHandle.dataset.dragYOffset = Math.max(0, event.clientY - selectionHandleClientRect.bottom + (lineHeight / 6));
@@ -748,10 +751,10 @@ function Highlighter(options = hhDefaultOptions) {
748
751
  }
749
752
  tapResult = null;
750
753
  longPressTimeoutId = clearTimeout(longPressTimeoutId);
754
+ this.annotatableContainer.dataset.hhPointerDown = 'false';
751
755
  if (activeSelectionHandle) {
752
756
  activeSelectionHandle = null;
753
757
  updateSelectionUi('bounds');
754
- this.annotatableContainer.dataset.hhDragging = 'false';
755
758
  this.annotatableContainer.removeEventListener('pointermove', respondToSelectionHandleDrag);
756
759
  }
757
760
  }
@@ -898,7 +901,7 @@ function Highlighter(options = hhDefaultOptions) {
898
901
  const highlightInfo = highlightsById[activeHighlightId] ?? null;
899
902
  const color = highlightInfo?.color ?? null;
900
903
  const style = highlightInfo?.style ?? null;
901
- const colorString = options.colors[color] ?? 'AccentColor';
904
+ const colorString = options.colors[color] ?? (CSS.supports('color', 'AccentColor') ? 'AccentColor' : 'dodgerblue');
902
905
 
903
906
  // Draw SVG selection rects (SVG drawing mode only)
904
907
  svgActiveOverlay.innerHTML = '';
@@ -953,7 +956,7 @@ function Highlighter(options = hhDefaultOptions) {
953
956
 
954
957
  } else if (changeType === 'bounds') {
955
958
  // Update selection handle location and visibility
956
- if (selection.type === 'Range' && activeHighlightId && pointerType === 'mouse' && !activeSelectionHandle) {
959
+ if (selection.type === 'Range') {
957
960
  const selectionRangeRects = selectionRange.getClientRects();
958
961
  const startRect = selectionRangeRects[0];
959
962
  const endRect = selectionRangeRects[selectionRangeRects.length-1];
@@ -961,8 +964,14 @@ function Highlighter(options = hhDefaultOptions) {
961
964
  const startNodeIsRtl = window.getComputedStyle(selectionRange.startContainer.parentElement).direction === 'rtl';
962
965
  const endNodeIsRtl = window.getComputedStyle(selectionRange.endContainer.parentElement).direction === 'rtl';
963
966
 
967
+ if (
968
+ (options.showCustomSelectionHandlesOnTouch || pointerType === 'mouse')
969
+ && ((options.showCustomSelectionHandlesForActiveHighlights && activeHighlightId)
970
+ || (options.showCustomSelectionHandlesForTextSelection && !activeHighlightId))
971
+ ) {
972
+ setCustomSelectionHandleVisibility(true);
973
+ }
964
974
  for (const selectionHandle of selectionHandles) {
965
- selectionHandle.style.visibility = 'visible';
966
975
  let side;
967
976
  if (selectionHandle.dataset.position === 'start') {
968
977
  side = startNodeIsRtl ? 'right' : 'left';
@@ -981,12 +990,17 @@ function Highlighter(options = hhDefaultOptions) {
981
990
  }
982
991
  }
983
992
  } else {
984
- selectionHandles[0].style.visibility = 'hidden';
985
- selectionHandles[1].style.visibility = 'hidden';
993
+ setCustomSelectionHandleVisibility(false);
986
994
  }
987
995
  }
988
996
  }
989
997
 
998
+ const setCustomSelectionHandleVisibility = (visible = selectionHandles[0].style.visibility === 'hidden') => {
999
+ for (const selectionHandle of selectionHandles) {
1000
+ selectionHandle.style.visibility = visible ? 'visible' : 'hidden';
1001
+ }
1002
+ }
1003
+
990
1004
  // Update the selection or highlight range to stay within the annotatable container
991
1005
  const snapRangeToBoundaries = (range, anchorNode = null) => {
992
1006
  let startNode = range.startContainer;
@@ -1308,8 +1322,8 @@ function Highlighter(options = hhDefaultOptions) {
1308
1322
  mergedRect.width = rect.width;
1309
1323
  }
1310
1324
  // Process then remove rects that apply to the current line
1311
- const minLeft = Math.min(mergedRect.x, rect.x);
1312
- const maxRight = Math.max(mergedRect.right, rect.right);
1325
+ const minLeft = Math.max(paragraphRect.left, Math.min(mergedRect.x, rect.x));
1326
+ const maxRight = Math.min(paragraphRect.right, Math.max(mergedRect.right, rect.right));
1313
1327
  mergedRect.width = maxRight - minLeft;
1314
1328
  mergedRect.x = minLeft;
1315
1329
  unmergedRects.splice(r, 1); r--;
@@ -1450,6 +1464,9 @@ let hhDefaultOptions = {
1450
1464
  defaultStyle: 'fill',
1451
1465
  defaultWrapper: 'none',
1452
1466
  highlightIdFunction: hhGetNewHighlightId,
1467
+ showCustomSelectionHandlesForActiveHighlights: true,
1468
+ showCustomSelectionHandlesForTextSelection: false,
1469
+ showCustomSelectionHandlesOnTouch: false,
1453
1470
  }
1454
1471
 
1455
1472
  console.info('Highlighter loaded');
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@samuelbradshaw/highlight-helper-js",
3
- "version": "0.7.5",
3
+ "version": "0.8.0",
4
4
  "description": "JavaScript tool that enables highlighting or underlining text in an HTML page.",
5
5
  "type": "module",
6
6
  "main": "highlight-helper.mjs",