Home > other >  How to detect the deselection of a before selected text?
How to detect the deselection of a before selected text?

Time:01-31

This may be a dumb question but I didn't find any information about this anywhere...

<input type="text" onselect="javascript: sel1 = true" placeholder="Suche nach etwas" id="browser1">

I have this line and at onselect the var sel1 is on true. Now this is the problem: I don't know how to do the opposite. I want to know how I can set the var sel1 to false when I deselect the input.

CodePudding user response:

The approach is as follows ...

  • Utilize a WeakMap instance as text-element based storage for a text-element's most recent text selection state.

  • Enable a text-elements deselect detection ...

    • ... by keeping track of such an element's 'select' event and selection state ...
    • ... and by following other events as well like e.g. 'keyup', 'mouseup' and 'focusout' where one always has to check the current selection state against the most recent one.
  • In case of having verified a deselection a custom event is created and dispatched. Thus one now can directly listen to and handle text element related 'deselect' events.

// gather all text control related selection data and put it
// into an object based (here the element reference) storage.
function putTextSelectionState(textControl) {
  const { value, selectionStart, selectionEnd } = textControl;

  const isSelected = (selectionEnd - selectionStart >= 1);
  const selection = value.substring(selectionStart, selectionEnd);

  textSelectionStorage.set(textControl, {
    isSelected,
    selection,
    selectionStart,
    selectionEnd,
    value,
  });
}
// the object based storage.
const textSelectionStorage = new WeakMap;

// detect whether custom 'deselect' event handling has to take place.
function handleDeselectText(evt) {
  const textControl = evt.currentTarget;
  const { selectionStart, selectionEnd } = textControl;

  // console.log({ type: evt.type, selectionStart, selectionEnd });

  const recentState = { ...textSelectionStorage.get(textControl) };
  putTextSelectionState(textControl);
  const currentState = { ...textSelectionStorage.get(textControl) };

  if (
    (selectionEnd - selectionStart === 0)
    && recentState.isSelected
  ) {
    // console.log('deselect');

    // a custom event will be created and dispatched in case ...
    // - there is nothing currently selected ... and ...
    // - there was a recent slection right before.
    textControl
      .dispatchEvent(
        new CustomEvent('deselect', {
          detail: {
            recentState,
            currentState,
          },
        })
      );
  }  
}
// update text control related selection data.
function handleSelectText({ currentTarget }) {
  putTextSelectionState(currentTarget);
}

// enable text related, custom 'deselect' event handling.
function initializeHandleDeselectText(textControl) {
  const nodeName = textControl.nodeName.toLowerCase();
  const textType = ((nodeName === 'textarea') && 'text')
    || ((nodeName === 'input') && textControl.type)
    || null;

  if (
    (textType === 'text') ||
    (textType === 'search') // ... or some more ...
  ) {
    putTextSelectionState(textControl);

    textControl.addEventListener('select', handleSelectText);

    textControl.addEventListener('input', handleDeselectText);
    textControl.addEventListener('keyup', handleDeselectText);
    textControl.addEventListener('mouseup', handleDeselectText);
    textControl.addEventListener('focusout', handleDeselectText); 
  }
}


// custom 'deselect' event handling.
function logTextDeselection(evt) {
  const { type, detail, currentTarget } = evt;

  console.log({ type, detail, currentTarget });
}
// native 'select' event handling.
function logTextSelection(evt) {
  const textControl = evt.currentTarget;

  const { value, selectionStart, selectionEnd } = textControl;
  const selection = value.substring(selectionStart, selectionEnd);

  console.log({ type: evt.type, selection });
}

function main() {
  const textControl = document.querySelector('#browser1');

  // enable text related, custom 'deselect' event handling.
  initializeHandleDeselectText(textControl);

  // native 'select' event handling.
  textControl.addEventListener('select', logTextSelection);

  // custom 'deselect' event handling.
  textControl.addEventListener('deselect', logTextDeselection);

  // default selected initial value.
  textControl.focus();
  textControl.value = 'The quick brown fox jumps over the lazy dog.';

  textControl.selectionStart = 12;
  textControl.selectionEnd = 19;

  // handle display of all available text selection states.
  document
    .querySelector('button')
    .addEventListener('click', () => console.log([
      ...document
      .querySelectorAll('textarea, input[type="text"], input[type="search"]')
    ].map(elmNode => ({
      elmNode,
      isSelected: textSelectionStorage.get(elmNode).isSelected
    }))));
}
main();
body { margin: 0; }
button { width: 27%; }
[type="search"] { width: 72%; }
.as-console-wrapper { min-height: 85%; }
<input id="browser1" type="search" placeholder="Search something ..."/>
<button>show select states</button>

CodePudding user response:

I would recommend creating a function which clears each of the variables which you are binding to the inputs. Inside each input's click event handler, you can invoke this function to clear any variables which may have been set previously. After invoking the function, set the variable which corresponds to that element.

Something along the lines of

function clearFlags() {
sel1 = false, sel2 = false, sel3 = false; // etc
}

and then your inline event handler could be

<input type="text" onselect="javascript: clearFlags(); sel1 = true" placeholder="Suche nach etwas" id="browser1">

CodePudding user response:

You could use onblur. This is called if you exit the input. For entring use onfocus instead of onselect (this is for a text selection in an input field).

let sel1, last = 0;
   
setInterval(() => {
    if (sel1 === last) return;
    console.log(sel1);
    last = sel1;
}, 200);
<input type="text" onfocus="javascript: sel1 = true" onblur="javascript: sel1 = false" placeholder="Suche nach etwas" id="browser1">

  •  Tags:  
  • Related