Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

does it support contenteditable? #17

Open
giorgio79 opened this issue Aug 21, 2014 · 2 comments
Open

does it support contenteditable? #17

giorgio79 opened this issue Aug 21, 2014 · 2 comments

Comments

@giorgio79
Copy link

I notice the readme mentions textarea only.

@jonathanong
Copy link
Contributor

negative. i think it's easier if you use contenteditable since you can do select range i believe. textareas and inputs don't have that luxury

@anotherCoward
Copy link

anotherCoward commented Dec 9, 2018

It can easily support it with a few changes and adding something like this, right at the beginning of the function:

function getCaretCoordinates(element, position, options) {
/*
isBrowser check..
*/
if (!element) {
  return getCaretCoordinates(document.activeElement || document.documentElement, position, options);
}
if (!element.isConnected) // in case of getCaretCoordinates(document.createElement('input'));
  return {
    top: 0,
    left: 0,
    height: 0,
    node: element
  }
if (options && options.absolute) {
  let relative = getCaretCoordinates(element, position),
    erect = element.getBoundingClientRect();
  return {
    top: erect.top + relative.top,
    left: erect.left + relative.left,
    height: relative.height, // remember kids, drugs are bad
    node: element
  }
}
let specials = ~['INPUT', 'TEXTAREA'].indexOf(element.nodeName);
if (position == null || !specials) {
  if (specials) {
    return getCaretCoordinates(element, element.selectionDirection == 'forward' ? element.selectionEnd : element.selectionStart);
  } else {
    if (window.getSelection().rangeCount) {
      let range = window.getSelection().getRangeAt(0),
        rect = range.getBoundingClientRect();
      // using the start or endcontainer is... uhm yeah... difficult...? :D
      let height = range.startContainer.nodeType == 1 ? getComputedStyle(range.startContainer).lineHeight : getComputedStyle(range.startContainer.parentNode).lineHeight;
      if (isNaN(height)) {
        let node = range.startContainer;
        if (range.startContainer.nodeType != 1) {
          node = node.parentNode;
        }
        let current = node.style.lineHeight;
        node.style.lineHeight = '1em';
        height = parseInt(getComputedStyle(node).lineHeight);
        node.style.lineHeight = current != null ? current : '';
        if (!node.getAttribute('style').length) { // clean up if empty
          node.removeAttribute('style');
        }
      }
      let erect = //thihihi
        element.getBoundingClientRect();
      return {
        top: rect.top - erect.top,
        left: rect.left - erect.left,
        height: height,
        node: element
      }
    } else {
      return {
        top: 0,
        left: 0,
        height: 0,
        node: element
      }
    }
  }
}
/*
 ... rest of the code
*/
}

This is compatible with all mayor browsers (add this range check for IE8, if you wanna support it).

One function that works for both types and returns the same output, is be really helpful. 👍

With this changes you could do:

getCaretPosition(); // returns the caret position, depending on the activeElement if any.
getCaretPosition(element); // returns the caret position inside that element
getCaretPosition(element, index); // same as before
getCaretPosition(null, null, { position: absolute }); // returns the absolute position of the caret depending on the current selected element

Greetings

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants