Просмотр исходного кода

Merge pull request #9309 from CroogQT/multiselect

Multiselect
Jeremy Stretch 3 лет назад
Родитель
Сommit
a71b2e231b

Разница между файлами не показана из-за своего большого размера
+ 0 - 0
netbox/project-static/dist/netbox.js


Разница между файлами не показана из-за своего большого размера
+ 0 - 0
netbox/project-static/dist/netbox.js.map


+ 2 - 0
netbox/project-static/src/buttons/index.ts

@@ -3,6 +3,7 @@ import { initDepthToggle } from './depthToggle';
 import { initMoveButtons } from './moveOptions';
 import { initReslug } from './reslug';
 import { initSelectAll } from './selectAll';
+import { initSelectMultiple } from './selectMultiple';
 
 export function initButtons(): void {
   for (const func of [
@@ -10,6 +11,7 @@ export function initButtons(): void {
     initConnectionToggle,
     initReslug,
     initSelectAll,
+    initSelectMultiple,
     initMoveButtons,
   ]) {
     func();

+ 105 - 0
netbox/project-static/src/buttons/selectMultiple.ts

@@ -0,0 +1,105 @@
+import { getElements } from '../util';
+import { StateManager } from 'src/state';
+import { previousPkCheckState } from '../stores';
+
+type PreviousPkCheckState = { element: Nullable<HTMLInputElement> };
+
+/**
+ * If there is a text selection, removes it.
+ */
+function removeTextSelection(): void {
+  window.getSelection()?.removeAllRanges();
+}
+
+/**
+ * Sets the state object passed in to the eventTargetElement object passed in.
+ *
+ * @param eventTargetElement HTML Input Element, retrieved from getting the target of the
+ * event passed in from handlePkCheck()
+ * @param state PreviousPkCheckState object.
+ */
+function updatePreviousPkCheckState(
+  eventTargetElement: HTMLInputElement,
+  state: StateManager<PreviousPkCheckState>,
+): void {
+  state.set('element', eventTargetElement);
+}
+
+/**
+ * For all checkboxes between eventTargetElement and previousStateElement in elementList, toggle
+ * "checked" value to eventTargetElement.checked
+ *
+ * @param eventTargetElement HTML Input Element, retrieved from getting the target of the
+ * event passed in from handlePkCheck()
+ * @param state PreviousPkCheckState object.
+ */
+function toggleCheckboxRange(
+  eventTargetElement: HTMLInputElement,
+  previousStateElement: HTMLInputElement,
+  elementList: Generator,
+): void {
+  let changePkCheckboxState = false;
+  for (const element of elementList) {
+    const typedElement = element as HTMLInputElement;
+    //Change loop's current checkbox state to eventTargetElement checkbox state
+    if (changePkCheckboxState === true) {
+      typedElement.checked = eventTargetElement.checked;
+    }
+    //The previously clicked checkbox was above the shift clicked checkbox
+    if (element === previousStateElement) {
+      if (changePkCheckboxState === true) {
+        changePkCheckboxState = false;
+        return;
+      }
+      changePkCheckboxState = true;
+      typedElement.checked = eventTargetElement.checked;
+    }
+    //The previously clicked checkbox was below the shift clicked checkbox
+    if (element === eventTargetElement) {
+      if (changePkCheckboxState === true) {
+        changePkCheckboxState = false;
+        return;
+      }
+      changePkCheckboxState = true;
+    }
+  }
+}
+
+/**
+ * IF the shift key is pressed and there is state is not null, toggleCheckboxRange between the
+ * event target element and the state element.
+ *
+ * @param event Mouse event.
+ * @param state PreviousPkCheckState object.
+ */
+function handlePkCheck(event: MouseEvent, state: StateManager<PreviousPkCheckState>): void {
+  const eventTargetElement = event.target as HTMLInputElement;
+  const previousStateElement = state.get('element');
+  updatePreviousPkCheckState(eventTargetElement, state);
+  //Stop if user is not holding shift key
+  if (!event.shiftKey) {
+    return;
+  }
+  removeTextSelection();
+  //If no previous state, store event target element as previous state and return
+  if (previousStateElement === null) {
+    return updatePreviousPkCheckState(eventTargetElement, state);
+  }
+  const checkboxList = getElements<HTMLInputElement>('input[type="checkbox"][name="pk"]');
+  toggleCheckboxRange(eventTargetElement, previousStateElement, checkboxList);
+}
+
+/**
+ * Initialize table select all elements.
+ */
+export function initSelectMultiple(): void {
+  const checkboxElements = getElements<HTMLInputElement>('input[type="checkbox"][name="pk"]');
+  for (const element of checkboxElements) {
+    element.addEventListener('click', event => {
+      removeTextSelection();
+      //Stop propogation to avoid event firing multiple times
+      event.stopPropagation();
+      handlePkCheck(event, previousPkCheckState);
+    });
+  }
+}

+ 1 - 0
netbox/project-static/src/stores/index.ts

@@ -1,2 +1,3 @@
 export * from './objectDepth';
 export * from './rackImages';
+export * from './previousPkCheck';

+ 6 - 0
netbox/project-static/src/stores/previousPkCheck.ts

@@ -0,0 +1,6 @@
+import { createState } from '../state';
+
+export const previousPkCheckState = createState<{ element: Nullable<HTMLInputElement> }>(
+  { element: null },
+  { persist: false },
+);

Некоторые файлы не были показаны из-за большого количества измененных файлов