0

I ran into an expanding textArea on code pen, https://codepen.io/vsync/pen/frudD It appears to work well. The code that drives it is:

$(document)
    .one('focus.autoExpand', 'textarea.autoExpand', function(){
        var savedValue = this.value;
        this.value = '';
        this.baseScrollHeight = this.scrollHeight;
        this.value = savedValue;
    })
    .on('input.autoExpand', 'textarea.autoExpand', function(){
        var minRows = this.getAttribute('data-min-rows')|0, rows;
        this.rows = minRows;
        rows = Math.ceil((this.scrollHeight - this.baseScrollHeight) / 16);
        this.rows = minRows + rows;
    });

Which I translated into Javascript as the following. Which also appears to be working well, and I do not get any errors on the console:

<!DOCTYPE html>
<head>
  <meta charset="UTF-8">
  <link rel="stylesheet" type="text/css" href="style.css">
</head>

<body>
<textarea class='autoExpand' rows='3' data-min-rows='3' placeholder='Auto-Expanding Textarea'></textarea>

  <script>
    'use strict'; 
    function handler_focusin(e){
      let savedValue = e.target.value;
      e.target.value = '';
      e.target.baseScrollHeight = e.target.scrollHeight;
      e.target.value = savedValue;
    }
    function handler_input(e){
      let minRows = e.target.getAttribute('data-min-rows')|0, rows;
      e.target.rows = minRows;
      rows = Math.ceil((e.target.scrollHeight - e.target.baseScrollHeight) / 16);
      e.target.rows = minRows + rows;
    }
    let els = document.getElementsByClassName("autoExpand");
    [...els].forEach( el => {
      el.addEventListener('focusin', handler_focusin);
      el.addEventListener('input', handler_input);
    })
  </script>
</body>

Questions:

  1. Look at the first statement in the function_handler (both in the JS version and the corresponding jQuery). There is an undeclared symbol 'rows' sitting there. There is a comma operator, so I would expect row to be evaluated, but there is no error in the console. Then two statements down rows is assigned to, again no declaration and no error.

    Also, why bother with the comma operator as rows is evaluated last and returned?

  2. In that same statement, I gather that 'data-min-rows' is a potentially programmer defined attribute, so unless that has been added, it will return undefined. I suppose then the the bitwise OR with zero that follows it, is to take precedence and that this returns zero.

    Correct?

  3. In jQuery apparently 'this' is the same as e.target. (found that in a couple of references). However, when I translated the code I missed changing a 'this' to an e.target, and it still worked.

    Is this also reliably e.target in a Javascript event handler? (The references I found from searches all appear to be talking about jQuery.)

  4. The jQuery code also assigns the event handlers to textarea.autoExpand but 'textarea' is not an event name. What is that doing? Is there something it corresponds to in Javascript?

Community
  • 1
  • 1
  • 2
    The comma is at the end of a variable declaration so it simply means that a second variable is to be declared with `let`. – Scott Marcus Jul 31 '19 at 14:55
  • As above: `var x=1,y;` is "shorthand" for `var x = 1; var y;` – freedomn-m Jul 31 '19 at 14:57
  • 1: `var a, b;` declares 2 variables, it's shorthand for `var a; var b;`. 2: `(undefined | 0) === 0`. 3: I'm not sure. 4: That's a delegate event handler. It listens for the `'focus.autoExpand'` event on a `textarea` with class `.autoExpand`. It's registered on the `document` so the event can be registered before the target element exists. – Cerbrus Jul 31 '19 at 14:58
  • 1
    This question really isn't appropriate for Stack Overflow because, first of all, it's not a single question and second it's more appropriate for a code review and should be posted to https://codereview.stackexchange.com/. Voting to close. – Scott Marcus Jul 31 '19 at 14:59
  • 2: this is so that `minRows` is never set to `undefined` – freedomn-m Jul 31 '19 at 14:59
  • 1
    I'm voting to close this question as off-topic because it belongs on https://codereview.stackexchange.com/ – Scott Marcus Jul 31 '19 at 14:59
  • 3: if `e.target == this` then you can use either, not sure why would expect this to not work – freedomn-m Jul 31 '19 at 14:59
  • freedomn-m, yeah my question is if in an event handler will always be e.target == this. Scott, I'll move it over there or delete it, unless anyone says something indicating it should be otherwise. But it would bbe a shame to lose these comments .. Scott can you move it all? –  Jul 31 '19 at 15:01
  • 4: to add to existing answer/comments the `x.y` format for the event is a namespaced event. You're converting a plugin that raises its own events. By using namespaces (in the format event.namespace.namespace) it ensures you can listen to the events just for that plugin and not other `input` events - i.e. reduces the possibility of event name clashes (no idea the javascript equivalent) – freedomn-m Jul 31 '19 at 15:06
  • 4: "*textarea.autoExpand but 'textarea' is not an event name*" - that's the selector for the delegated event, not an event name. – freedomn-m Jul 31 '19 at 15:07
  • @freedomn-m: They're just event names. JS doesn’t have a concept of “event namespaces”. Functionally, there's no difference between `"foo.bar"` and `"foobar"`, but it _is_ a good convention :-) – Cerbrus Jul 31 '19 at 15:08
  • @Cerbrus Indeed, there's no "namespaces" as such in the *conventional* sense. The key information is that it's a custom event for that plugin. There *is* a difference between "input" and "input.myplugin". – freedomn-m Jul 31 '19 at 15:24
  • No, I can't move the question. – Scott Marcus Jul 31 '19 at 15:44
  • @ScottMarcus I have more questions about this code (for example the '16' scale). I will open another discussion there and reference what is here. This is essentially finished anyway as there is an answer. Good enough? or would you prefer another approach? This is my first time to run into such an issue. I'll be sure to be more careful next time. –  Jul 31 '19 at 16:02
  • `16` is likely the assumed pixel height to calculate number of rows – freedomn-m Jul 31 '19 at 16:03
  • 1
    It would be best for you to post a new question on the other site, but make it a complete question over there, rather than referencing this question here as this question could get deleted over time because it's off-topic for this site. When you post here, you should ask a single question about a specific programming issue that you are having. Having code explained is not for Stack Overflow. – Scott Marcus Jul 31 '19 at 16:16

1 Answers1

0
  1. var a, b; declares 2 variables, it's shorthand for var a; var b;.

  2. myVariable | 0 "casts" the variable to a number:
    "wadsd" | 0 > 0
    undefined | 0 > 0
    true | 0 > 1
    123 | 0 > 123

3: Yes, this refers to e.currentTarget. (source)

4: That's a delegated event handler. It listens for the 'focus.autoExpand' event on a textarea with class .autoExpand. It's registered on the document so the event can be registered before the target element exists.

Cerbrus
  • 70,800
  • 18
  • 132
  • 147