読者です 読者をやめる 読者になる 読者になる

みかづきブログ その3

3ヶ月つづけてみました。

JavaScriptとCSSの力をつかってEメールアドレスを途中まで入力したらドメイン以下をサジェストするフォームをつくる

See the Pen Form for Email by kimmy (@kimmy) on CodePen.

タイトルのとおりです。
@以下の一文字をタイプしたときに、
@gmail.com, @yahoo.co.jp, @hotmail.co.jp, @docomo.ne.jp, @ezweb.ne.jp, @softbank.ne.jp をサジェストします。


ソースコード

HTML
<div class="input-box">
  <input type="text" placeholder="E-Mail" class="input"/>
  <div data-domain="" class="suggest"><span class="btn close">×</span></div>
</div>
SCSS
body {
  background: #ECEFF1;
}

.input-box {
  $domain : "gmail.com", "yahoo.co.jp", "hotmail.co.jp", "docomo.ne.jp", "ezweb.ne.jp", "softbank.ne.jp";

  position: absolute;
  top: 0; bottom: 0; left: 0; right: 0;
  margin: auto;
  width: 600px; height: 60px;
  
  .input {
    box-sizing: border-box;
    display: block;
    margin: 0 auto 40px;
    border: none;
    border-radius: 10px;
    padding: 20px;
    width: 100%; height: 60px;
    font: 20px "Avenir Next";
    box-shadow: 0 0 2px rgba(0, 0, 0, .5) inset;
    -webkit-appearance: none;
    
    &:focus {
      outline: none;
    }
  }

  .suggest {
    display: none;
    position: absolute;
    bottom: -40px; right: 0;
    padding: 4px 56px 4px 4px;
    border: solid 1px #90CAF9;
    border-radius: 4px;
    color: #1E88E5;
    font: 20px "Avenir Next";
    background: #fff;
    cursor: pointer;
    -webkit-user-select: none;

    &:hover {
      color: #fff;
      background: #90CAF9;
    }

    @each $key in $domain {
      &[data-domain="#{$key}"] {
        display: block;

        &:before {
          content: "@#{$key}";
        }
      }
    }

    .btn {
      box-sizing: border-box;
      position: absolute;
      top: 50%; right: 8px;
      margin-top: -8px;
      width: 16px; height: 16px;
      border-radius: 50%;
      color: #B0BEC5;
      font-size: 10px;
      line-height: 16px;
      text-align: center;
      background: #ECEFF1;
    }

    &.on {
      display: block;
    }
  }
}

JavaScript

(function(win) {
  
  "use strict";
  
  win.App = {};
  
})(this);

(function(win, doc, ns, $) {

  "use strict";

  function EmailInput(elm) {
    var that = this;

    _init();

    function _init() {
      that.input   = elm.querySelector(".input");
      that.suggest = elm.querySelector(".suggest");
      that.timer   = null;

      that._clearSaddest = that._clearSaddest.bind(that);
      that._handleKeyUp  = that._handleKeyUp.bind(that);
      
      that.input.addEventListener("focus", _handleFocus, false);
      that.input.addEventListener("blur", _handleBlur, false);
      that.suggest.addEventListener("click", _handleClick, false);
    }
    
    function _handleFocus() {
      that._handleFocus();
    }
    
    function _handleBlur() {
      that._handleBlur();
    }
    
    function _handleClick(evt) {
      that._handleClick(evt);
    }
  }

  EmailInput.CONST = {
    DOMAIN_OBJ : {
      g : ["gmail.com"],
      y : ["yahoo.co.jp"],
      h : ["hotmail.co.jp"],
      d : ["docomo.ne.jp"],
      e : ["ezweb.ne.jp"],
      s : ["softbank.ne.jp"]
    }
  };

  EmailInput.prototype._displaySaddest = _displaySaddest;
  EmailInput.prototype._clearSaddest   = _clearSaddest;
  EmailInput.prototype._handleFocus    = _handleFocus;
  EmailInput.prototype._handleBlur     = _handleBlur;
  EmailInput.prototype._handleKeyUp    = _handleKeyUp;
  EmailInput.prototype._handleClick    = _handleClick;
  EmailInput.prototype._checkDomain    = _checkDomain;

  function _displaySaddest(domain) {
    var that = this;

    that.suggest.setAttribute("data-domain", domain);
  }

  function _clearSaddest() {
    var that = this;

    that._displaySaddest("");
  }

  function _handleFocus() {
    var that = this;

    doc.addEventListener("keyup", that._handleKeyUp, false);
  }

  function _handleBlur() {
    var that = this;

    doc.removeEventListener("keyup", that._handleKeyUp, false);
    that.timer = setTimeout(that._clearSaddest, 200); // suggestをタップした際の対策
  }

  function _handleClick(evt) {
    var that = this,
        domain;

    if (!evt.target.classList.contains("btn")) {
      domain = that.suggest.getAttribute("data-domain");
      that.input.value = that.input.value.replace(/\@.*$/, "@" + domain);
    }

    that._clearSaddest();
  }

  function _handleKeyUp() {
    var that = this;

    that._checkDomain(that.input.value);
  }

  function _checkDomain(txt) {
    var that   = this,
        domain = "",
        regExp;
    
    $.each(EmailInput.CONST.DOMAIN_OBJ, function(key, val) {
      regExp = new RegExp("[a-zA-Z0-9]\@" + key);
      if (regExp.test(txt)) {
        domain = EmailInput.CONST.DOMAIN_OBJ[key][0];
      }
    });

    if (domain) {
      that._displaySaddest(domain);
    } else {
      that._clearSaddest();
    }
  }

  ns.EmailInput = EmailInput;

})(this, document, App, jQuery);

(function EmailInput(win, doc, ns) {
  
  "use strict";
  
  new ns.EmailInput(doc.querySelector(".input-box"));

})(this, document, App);

わりと便利に使えます。