フォームなどで使う文字列周りの処理

フォーム周りの対応でよく使いそうなjs処理を備忘録程度に書いておきます。


## maxlengthの対応

基本的にはこれで良さそうだけれども、マルチバイト対策が必要な可能性があるようです。

```html
<input type="text" maxlength="20">
```

また、古いブラウザだと対応してなかったりするので、以下のように最大文字数超えたら消すようにしています。

```js:jQuery
  $('input[type^="text"]').on('input', function() {

    const maxLength = $(this).attr('maxlength');
    const strValue = $(this).val();

    if (strValue.length > maxLength) {
        $(this).val( strValue.slice(0, maxLength) );
    }

  });
```



## 空行の判定

```js:isEmpty.js
  function isEmpty(strArr) {

    for(let i = 0; i < strArr; i++) {
      if( strArr[i].replace(/\s*/g, '') === '' ) return = true;
    }

    return false;

  }
```



## NGワード検出
超簡単なNGワード検出。

この場合、語尾につける「〜だしね」などもNGワードとして検出してしまうので、注意してください。
NGワードは大量にある場合がほとんどなので、jsonなどで別ファイルから読み込んでもいいかと思います。

```data/ngwords.json
{
  "data": ["アダルト", "AV", "死ね", "しね"]
}
```

```js:hasNGWords.js
// JSONデータの読み込み
let ngwords = [];
$.getJSON('data/ngwords.json', json => {
  ngwords = json.data;
});

function hasNGWords(str, ngwords) {

  for(let i = 0; i < ngwords.length; i++) {
    if(~str.indexOf(ngwords[i])) return true;
  }

  return false;

}
```


## 行数のカウント
`<textarea>`であれば、`DOM.scrollHeight`で要素内の高さが取れます。
ただし、初期の高さは`<textarea>`の高さになるので、それ以下の場合は表示させないか別の計算をしなければいけなさそうです。

```js
function countLine() {

  // カウントしたいテキスト入力欄のDOM
  // jQueryの場合は$('#textform')[0]
  const textarea = document.getElementById('textform');

  // 文字の高さ(line-height込み、単位はpx)
  const TEXT_HEIGHT = 24;

  return Math.floor(textarea.scrollHeight / TEXT_HEIGHT);

}
```


## ゼロパディング

以下の記事で紹介しているのが利用できます。
[javascriptでゼロ埋め](http://qiita.com/_shimizu/items/2cb49daf2eb8ffb30690)


## placeholderの複数行対応

現存サイトで書かれてある

- CSSの`after`で`/a`使う
- 実際にplaceholder属性内で改行させておく

などの対応だと、ブラウザごとに対応・非対応が難しいので、プログレッシブ・エンハンスメントなどを考えないかぎりしないほうが良いです。

現状ではjsでvalの属性を置き換えるのが良いかと思います。
`focus blur`時の挙動が実際のplaceholderとはちがいますが、問題ないレベルだと思います。

この記事のコードを利用しています。
[HTML5のplaceholder属性をjQueryでやってみる](https://havelog.ayumusato.com/develop/javascript/entry-86.html)

```js:placeholder.js

  $('.is-placeholder').each(function() {
    let elem = $(this);
    const DEFAULT_PLACEHOLDER_COLOR = 'silver';

    (function(elm) {

      $.data(elm, 'placeholder-string', $(elm).attr('value'));
      $.data(elm, 'placeholder-color', $(elm).css('color'));

      switch ( $(elm).val() ) {
          case '' :
              $(elm).val($.data(elm, 'placeholder-string'));
          case $.data(elm, 'placeholder-string') :
              $(elm).css('color', DEFAULT_PLACEHOLDER_COLOR);
          break;
      }
      $(elm).focus(function() {
          if($(this).val() == $.data(this, 'placeholder-string')) {
              $(this).val('');
              $(this).css('color', $.data(this, 'placeholder-color'));
          }
      });
      $(elm).blur(function() {
          if($(this).val() == '') {
              $(this).val($.data(this, 'placeholder-string'));
              $(this).css('color', DEFAULT_PLACEHOLDER_COLOR);
          }
      });
    })(this)

  });
```



## 参考記事

- [HTML5におけるinput要素のpattern、type属性のおさらい](http://qiita.com/ka215/items/795a179041c705bef03b#pattern%E5%B1%9E%E6%80%A7%E3%81%8C%E6%9C%89%E5%8A%B9%E3%81%AAtype%E5%B1%9E%E6%80%A7)
- [String.prototype.indexOf() - JavaScript | MDN](https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/String/indexOf)