みかづきブログ その3

本ブログは更新を終了しました。通算140万ユーザーの方に観覧頂くことができました。長い間、ありがとうございました。

👆

引越し先はこちらです!

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);

わりと便利に使えます。