jm-david / emoji-mart-vue

One component to pick them all 👊🏼
https://jm-david.github.io/emoji-mart-vue
BSD 3-Clause "New" or "Revised" License
603 stars 82 forks source link

Docs: using with contenteditable #22

Open keligijus opened 6 years ago

keligijus commented 6 years ago

I can't figure out the example of using <emoji> component inside contenteditable. It seems that the example has been taken from original React lib and is a React example.

Is it possible to achieve similar in Vue?

jm-david commented 6 years ago

You're right, that example did come from React and I haven't been able to recreate the functionality. I've temporarily removed that section of the readme to prevent confusion. Will update this issue if I'm able to figure it out.

bujji1 commented 5 years ago

@jm-david @keligijus did you guys get any solution for this ? Thank you .

keligijus commented 5 years ago

Nope, no luck, if I remember well, I had to take a different approach.

bujji1 commented 5 years ago

@keligijus - No luck for me . I tried 1) Getting the current carrot position of div 2) Saving the position 3) Getting the contents of the clicked emoji 4) Inserting the contents of the clicked emoji at the saved position in the 2nd step .

But this is all messing up . You said you took a different approach . If you don't mind can I know the approach that you took .

Thanks

keligijus commented 5 years ago

@bujji1 what is failing in your solution?

bujji1 commented 5 years ago

It is not consistent and also I can not able to delete it id user wants to delete it with Backspace. The approach I took is kind of fake .

You can see the first "tempId" below , this is what holds the current emoji whatever user selected . I read the content from this Div and add it to my "ContentEditable " Div . :)

    <div
      id="tempId"
      style="position:fixed;top:-30px;"
    >
      <emoji
        :emoji="currentEmoji"
        set="twitter"
        :size="25"
      />
    </div>
` getNodeIndex(n) {
      var i = 0;
      while ((n = n.previousSibling)) i++;
      return i;
    },

    saveRangePosition() {
      try {
        var range = window.getSelection().getRangeAt(0);
        var sC = range.startContainer,
          eC = range.endContainer;

        let A = [];
        while (sC !== k1Editor) {
          A.push(this.getNodeIndex(sC));
          sC = sC.parentNode;
        }
        let B = [];
        while (eC !== k1Editor) {
          B.push(this.getNodeIndex(eC));
          eC = eC.parentNode;
        }
        window.rp = {
          sC: A,
          sO: range.startOffset,
          eC: B,
          eO: range.endOffset
        };
      } catch (err) {}
    },

    restoreRangePosition() {
      try {
        let k1Editor = document.getElementById("k1Editor");
        k1Editor.focus();
        var sel = window.getSelection(),
          range = sel.getRangeAt(0);
        var x,
          C,
          sC = k1Editor,
          eC = k1Editor;

        C = rp.sC;
        x = C.length;
        while (x--) sC = sC.childNodes[C[x]];
        C = rp.eC;
        x = C.length;
        while (x--) eC = eC.childNodes[C[x]];

        range.setStart(sC, rp.sO);
        range.setEnd(eC, rp.eO);
        sel.removeAllRanges();
        sel.addRange(range);
      } catch (err) {}
    },

    insertTextAtCursor(text) {
      self=this;
      var sel, range, html;
      sel = window.getSelection();
      range = sel.getRangeAt(0);
      range.deleteContents();
      var textNode = document.createTextNode("\u00A0");

      setTimeout(function() {
        var MyDiv1 = document.getElementById("tempId").innerHTML;

        var nnode = document.createElement("b");
        nnode.innerHTML = MyDiv1;
        range.insertNode(nnode);
        range.setStartAfter(nnode);

        range.insertNode(textNode);
        range.setStartAfter(textNode);
        sel.removeAllRanges();
        sel.addRange(range);
        self.saveRangePosition();
      }, 100);
    },

    addEmoji(emoji) {
      self = this;
      this.restoreRangePosition();
      console.log(emoji);
      this.currentEmoji = emoji.id;
      this.count++;
      this.insertTextAtCursor(emoji.native);
      setTimeout(function() {
        self.dataHTML = document.getElementById("k1Editor").innerHTML;
        self.$emit("dataHTML", self.dataHTML);
      }, 100);
    },`
keligijus commented 5 years ago

@bujji1 this seems like a Stack Overflow type of question. Managing caret position is really messy in content editable.

If I recall correctly, my solution was to deal with native emojis when inserting them. This way it's just another text node and caret position seems a lot easier to manage when you only care about text nodes.

Sorry, I am not sure if I can help you more. This lib is not dealing with caret positioning, that's something we need to do ourselves :|

vedmant commented 5 years ago

I have the same issue and I need to use custom emojis so I need to insert images into contenteditable, for now I couldn't figure out how to make it work correctly. Currently I'm trying to render EmojiNimble component into a string and insert that into contenteditable, but couldn't figure out how to render VNode into a string.

agb commented 2 years ago

You can look at this article Thank you Konstantin Münster

https://javascript.plainenglish.io/how-to-find-the-caret-inside-a-contenteditable-element-955a5ad9bf81

https://9tq3o.csb.app/