0

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.

Peter Seliger
  • 11,747
  • 3
  • 28
  • 37
Jan
  • 1
  • 4
  • Have you tried onblur="sel1=false" ? I hope this could help. – Mr_NAIF Jan 28 '22 at 21:30
  • Does this answer your question? [Call a function after leaving input field](https://stackoverflow.com/questions/38791919/call-a-function-after-leaving-input-field) – isherwood Jan 28 '22 at 21:40
  • just for noticing ... a `blur` event type is not the opposite of a `select` event type. Since the latter is dispatched for `text` type input fields and textareas whenever a text gets selected, the opposite was the deselection of such a text and not the defocusing of the element itself (it is possible to have selected text while having lost the element focus). – Peter Seliger Jan 28 '22 at 21:46
  • @Jan ... thus said. What is/was the purpose anyhow of handling the `select` event in first place? – Peter Seliger Jan 28 '22 at 21:50
  • @Jan ... Regarding the provided answers / solutions / approaches are there any questions left? – Peter Seliger Feb 06 '22 at 16:06
  • @Jan ... At SO it is considered to be a nice gesture from the one who got help, to provide some feedback (don't just disappear) and/or accept the answer which was the most helpful in solving the OP's problem. – Peter Seliger Mar 09 '22 at 15:06

3 Answers3

0

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>
Peter Seliger
  • 11,747
  • 3
  • 28
  • 37
-1

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">
Nina Scholz
  • 376,160
  • 25
  • 347
  • 392
  • The opposite of *select* is a *deselect* and not loosing the focus. The OP handles text selection events of a text input. Thus handling `blur` most probably is not the correct solution. – Peter Seliger Jan 28 '22 at 21:53
  • @PeterSeliger `deselect` is not [available](http://jsfiddle.net/Shef/wF2qN/). – Nina Scholz Jan 28 '22 at 22:43
  • I know, that's why one has to detect it from handling a lot of other events and maybe even create a custom/artificial *text related* `deselect` event. – Peter Seliger Jan 28 '22 at 23:28
-1

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">
pawooten
  • 140
  • 1
  • 9