determine if selection contains rich text

33 views
Skip to first unread message

Mika Genic

unread,
Feb 11, 2016, 6:52:17 PM2/11/16
to Firepad
what would be the write way to determine if the current selection contains rich text ?

would it be enough to do cm.getSelection() and check if there are any sentinels ?

thx!

Michael Lehenbauer

unread,
Feb 11, 2016, 6:59:53 PM2/11/16
to Mika Genic, Firepad
That won't be enough.  Most rich-text formatting (color, font, etc.) isn't done with sentinels.

You'd probably need to:
1) get the start/end pos of the selection.
2) call firepad.getOperationForSpan(start, end)
3) Iterate over the operation.ops and see if any of them have a non-empty .attributes object.

Hope that helps,
-Michael

--
You received this message because you are subscribed to the Google Groups "Firepad" group.
To unsubscribe from this group and stop receiving emails from it, send an email to firepad-io+...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/firepad-io/ca323d63-88a8-4289-810e-a893f1af5b6d%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Message has been deleted

Mika Genic

unread,
Feb 11, 2016, 10:44:24 PM2/11/16
to Firepad, mika...@gmail.com
I came up with this which seems to work:

  Firepad.prototype.selectionHasAttributes = function() {
    var startPos = this.codeMirror_.getCursor('start'), endPos = this.codeMirror_.getCursor('end');
    var startIndex = this.codeMirror_.indexFromPos(startPos), endIndex = this.codeMirror_.indexFromPos(endPos);
    return this.rangeHasAttributes(startIndex, endIndex);
  };

  Firepad.prototype.rangeHasAttributes = function(start, end) {
    this.assertReady_('rangeHasAttributes');
    var doc = (start != null && end != null) ?
      this.getOperationForSpan(start, end) :
      this.getOperationForSpan(0, this.codeMirror_.getValue().length);

    var i = 0, op = doc.ops[i];    
    while(op) {
      var attrs=op.attributes;
      if (!attrs) continue;

      if (ATTR.LINE_INDENT in attrs || ATTR.LIST_TYPE in attrs || ATTR.LINE_ALIGN in attrs) return true; // found a line attribute

      if (ATTR.BOLD in attrs || ATTR.ITALIC in attrs || ATTR.UNDERLINE in attrs || ATTR.STRIKE in attrs || ATTR.FONT in attrs || 
          ATTR.FONT_SIZE in attrs || ATTR.COLOR in attrs || ATTR.BACKGROUND_COLOR in attrs) return true; // found an entity attribute

      op = doc.ops[++i];
    }

    // this.entityManager_ ???
    return false;
  };


- does this looks correct ?

- should I worry about something in this.entityManager_ ? I see entityManager has it's own element.hasAttribute(attr) ?

thx !

Michael Lehenbauer

unread,
Feb 12, 2016, 11:13:40 AM2/12/16
to Mika Genic, Firepad
The first version (that checks for *any* attributes using "for (var prop in op.attributes)" looks more correct to me.  The second version might break in the future if we add new attributes.

Other than that, I think this looks correct.  It'd probably be better to use a "for (var i = 0; i < doc.ops.length; i++) { var op = doc.ops[i];  ... }" loop rather than let "op = doc.ops[++i]" read past the end of the array.

You shouldn't need to worry about entityManager.

Thanks,
-Michael

--
You received this message because you are subscribed to the Google Groups "Firepad" group.
To unsubscribe from this group and stop receiving emails from it, send an email to firepad-io+...@googlegroups.com.

Mika Genic

unread,
Feb 12, 2016, 4:26:01 PM2/12/16
to Firepad, mika...@gmail.com
thx ! the thing is the first version also check for ATTR.ENTITY_SENTINEL. I am not sure exactly what is the role of ENTITY_SENTINEL (and would love if you explain). Looking at serializeHtml code it seems it does not add any formatting to the final html so should not be used to determine rich text. What do you think ?

(this is all work towards rich text copy/cut/paste PR , so the idea is to use the non rich text CM code if we're not dealing with rich text, testing with this code)

Michael Lehenbauer

unread,
Feb 12, 2016, 4:34:27 PM2/12/16
to Mika Genic, Firepad
ENTITY_SENTINEL is used for embedded entities which are used for non-text things in the document...  the most common example is an image, but it's extensible so you could define other kinds.

Images are included in serializeHTML() I think.

-Michael

--
You received this message because you are subscribed to the Google Groups "Firepad" group.
To unsubscribe from this group and stop receiving emails from it, send an email to firepad-io+...@googlegroups.com.

Mika Genic

unread,
Feb 12, 2016, 8:24:49 PM2/12/16
to Firepad, mika...@gmail.com
so considering https://github.com/firebase/firepad/issues/234

and until it is fixed I ended up with:

  Firepad.prototype.selectionHasAttributes = function() {
    var startPos = this.codeMirror_.getCursor('start'), endPos = this.codeMirror_.getCursor('end');
    var startIndex = this.codeMirror_.indexFromPos(startPos), endIndex = this.codeMirror_.indexFromPos(endPos);
    return this.rangeHasAttributes(startIndex, endIndex);
  };

  Firepad.prototype.rangeHasAttributes = function(start, end) {
    this.assertReady_('rangeHasAttributes');
    var doc = (start != null && end != null) ?
      this.getOperationForSpan(start, end) :
      this.getOperationForSpan(0, this.codeMirror_.getValue().length);

    var op;
    for (var i = 0; i < doc.ops.length; i++) { 
      op = doc.ops[i];   
      for(var prop in op.attributes) if (op.attributes.hasOwnProperty(prop) && prop!=ATTR.LINE_SENTINEL) return true; // found an attribute
    }
    
    return false;
  };

does this looks ok ?

Michael Lehenbauer

unread,
Feb 15, 2016, 2:58:03 PM2/15/16
to Mika Genic, Firepad
Yep, I think so!

--
You received this message because you are subscribed to the Google Groups "Firepad" group.
To unsubscribe from this group and stop receiving emails from it, send an email to firepad-io+...@googlegroups.com.
Reply all
Reply to author
Forward
0 new messages