guardian / scribe

DEPRECATED: A rich text editor framework for the web platform

Home Page:http://guardian.github.io/scribe/

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

node.elementHasClass arguments

mindplay-dk opened this issue · comments

What's going on here?

  function elementHasClass(Node, className) {
    return function(node) {
      return (node.nodeType === Node.ELEMENT_NODE && node.className === className)
    }
  }

  function isSelectionMarkerNode(node) {
    return elementHasClass(Node, 'scribe-marker')(node);
  }

  function isCaretPositionNode(node) {
    return elementHasClass(Node, 'caret-position')(node);
  }

  function isNotObservableNode(node) {
    return elementHasClass(Node, 'scribe-not-observable')(node);
  }

Why is Node being passed as an argument?

For the sake of testing?

The test is the only place that function is actually being called from outside - perhaps this was intended as an internal function supporting those other three functions? It's being exported though.

Yes exactly it makes the function work only on it's parameters rather than global state. The base function is the "general" case and the other three are specialisations designed for readability.

Yes exactly it makes the function work only on it's parameters rather than global state.

Not really - you're still grabbing the Node global in those three functions, so the net result is dependency on the Node global for all of the functions that are actually called from outside.

You might as well simplify:

  function elementHasClass(node, className) {
    return (node.nodeType === Node.ELEMENT_NODE && node.className === className)
  }

  function isSelectionMarkerNode(node) {
    return elementHasClass(node, 'scribe-marker');
  }

  function isCaretPositionNode(node) {
    return elementHasClass(node, 'caret-position');
  }

  function isNotObservableNode(node) {
    return elementHasClass(node, 'scribe-not-observable');
  }

This saves the overhead of creating and executing an extra function on-the-fly for every call to those three functions.

The base function is the "general" case and the other three are specialisations designed for readability.

There is no case where the "general" function is actually used from the outside - it's used only internally by those three functions, all of which depend on the Node global.

If you're concerned about accessing the Node global, perhaps the thing to do is to import it?

Just like you're doing for other global dependencies, such as MutationObserver.

It's a global dependency for the special-case functions not the underlying implementation.

I would generally trade readability for performance overhead. But feel free to attach some performance tests to illustrate the difference, I've been known to change my mind in the past!

IMO elementHasClass(Node, 'caret-position')(node) looks peculiar.

I find elementHasClass(node, 'caret-position') is much easier to read. (and understand.)

I guess that's a matter of opinion :-)

Learn to love the Curry! (Node)('caret-position')(node) would probably be better but I'm a bit lazy.

Learn to love the Curry!

Learn to KISS ;-)

  function elementHasClass(Node, className) {
    return function(node) {
      return (node.nodeType === Node.ELEMENT_NODE && node.className === className)
    }
  }

  /* delete redundant functions */

  return {
    isSelectionMarkerNode: elementHasClass(Node, 'scribe-marker'),
    isCaretPositionNode: elementHasClass(Node, 'caret-position'),
    isNotObservableNode: elementHasClass(Node, 'scribe-not-observable'),
    // ...
  }

At least then you're not recreating the functions on every call for no reason.

Yeah, that's a fair improvement.

Tried it today and I the reference to Node in the exports breaks compilation as Node needs to be resolved at compilation.

Lazy is actually better.