frontendmemo

このサイトは、「html、css、js、ツールなどについて、自分が覚えたこと、またはいつも忘れて調べることを書き溜め、それが結果といて勉強したての初心者の方や自分と同じような技術レベルの人の助けになることを目的とするWebログ」、略してブログです。挨拶→http://frontendmemo.hatenablog.com/entry/2016/06/25/115845

【JavaScript】クロージャを使って10回ボタンを押したらアラートを出す

下記を参考にクロージャを使って10回ボタンを押したらアラートを出してみたいと思います。

[JavaScript] 猿でもわかるクロージャ超入門 5 クロージャを作る · DQNEO起業日記

クロージャの条件

  • 外の関数のスコープ内で変数を定義し、
  • 外の関数の中に関数(=関数内関数)を作って
  • その関数内関数から、先ほどの変数を参照する

クロージャの利点

  • 「状態を保持する関数」を作ることができます。
function count(){
    var x = 1;
    return function (){   
      x += 1;
      if(x === 10){
         alert('10回押されました');
       }
    };
}

var aler =  count(); 
$('button').on('click', function(){
  aler();
});

DEMO

See the Pen eWNXRV by funclur (@funclur) on CodePen.

【JavaScript】モジュールパターンを学ぶ~スムーススクロール機能を実装~

モジュールパターンというものを最近知りました。プラグインでよく使われてる手法なのかなと思います。

モジュールパターンの参考記事

なぜモジュールパターンを使うか

上の記事によると利点は以下だそうです。

  • 他の処理との競合を防ぐ
  • 追加・置き換え・削除ができる
  • 機能別にコードを分割できる

といってもコードを書いてみないとわかりません。
上記記事を参考にしながら、スムーススクロールをモジュールパターンに置き換えてみました。

通常のスクリプト

  'use strict';
  var $win = $(window);
  /**
  * スムーススクロール
  */
  $.fn.smoothScroll = function(options){
    if(!this.length || this.attr('href') === '#'){
      return;
    }
    var o = $.extend({
      speed : 300, // スクロールの速度
      easing : 'swing' // スクロールの速度
    }, options);
    var self = this,
      speed  = o.speed,
      easing = o.easing,
      target, position, targetHref,
      hash = window.location.hash,
      // ブラウザを判定し対応している要素を変数にsetする
      $targetBody = $('html').scrollTop() > 0? $('html'): $('body');
    // 読み込み時にURLに#がある場合

    if(hash){
      $win.on('load', function(){
        self.trigger('click');
      });
    }
    this.on('click', function(){
      var $self = $(this);
      scroll($self);
    });
    // スクロールさせる関数
    function scroll($self){
      setPosition($self);
      $targetBody.not(':animated').animate({
        scrollTop : position
      }, speed, easing);
    }
    // 移動先の数値を取得するための関数
    function setPosition($self){
      // hrefの値を取得
      targetHref = $self.attr('href');
      // 移動先をアンカーを取得
      target = $(targetHref === '#top' ? $targetBody : targetHref);
      // 移動先の数値を取得
      position = target.offset().top;
    }
  };
  $('a[href^="#"]').smoothScroll();
})(window.jQuery);

モジュールパターンを使用したスクリプト

window.jQuery && (function ($) {
  'use strict';
  var $win = $(window);
  /**
  * スムーススクロール
  */
  var smoothScroll = smoothScroll || {
    util: {
      obj: {}
    }
  };
  smoothScroll.util.obj = (function(){
    var self = $('a[href^="#"]'),
      speed  = 300,
      easing = 'swing',
      target, position, targetHref,
      hash = window.location.hash,
      // ブラウザを判定し対応している要素を変数にsetする
      $targetBody = $('html').scrollTop() > 0? $('html'): $('body');

     var click = function(target){
      target.on('click', function(){
        var $self = $(this);
        smoothScroll.util.obj.scroll($self);
      });
    },
    scroll = function($self){
    // スクロールさせる関数a
      smoothScroll.util.obj.setPosition($self);
      $targetBody.not(':animated').animate({
        scrollTop : position
      }, speed, easing);
    },
    // 移動先の数値を取得するための関数a
    setPosition = function($self){
      // hrefの値を取得
      targetHref = $self.attr('href');
      // 移動先をアンカーを取得
      target = $(targetHref === '#top' ? $targetBody : targetHref);
      // 移動先の数値を取得
      position = target.offset().top;
    },
    init = function(){
      if(hash){
        $win.on('load', function(){
          $('a[href="' + hash + '"]').trigger('click');
        });
      }
    }
    init();
    return {
      click: click,
      scroll: scroll,
      setPosition: setPosition
    };
  })();
  smoothScroll.util.obj.click($('a[href^="#"]'));
})(window.jQuery);

DEMO

See the Pen oBxQbP by funclur (@funclur) on CodePen.


まとめ

以上、スムーススクロール機能をモジュールパターンに置き換えてみました。
詳しい説明は、自分が未だよくわかっていないので上記記事をご覧ください。
また、通常のスクリプトもグローバル環境汚染してるわけじゃないし、機能も追加できるし、はっきりとした利点が良くわかっていません。
ただかっこいいからモジュールパターン使っていこうかなという感じ笑

分かってきたらまた、ブログを更新するとします。

要素の増減でページ遷移のアンカーリンクの位置がずれる

アンカーリンクとはリンク先urlを例えば../index.html#anchorとしておくとクリックした時、id="anchor"とidを振った要素にスクロール位置が合うようになります。
またそれは同一ページでも別ページでもいけるんですね。

<a href="../index.html#anchor">アンカーリンク</a>
<h2 id="anchor">見出し</h2>

上記のようにすれば見出しのところまでジャンプします。

しかし、こちらタイトルの通り落とし穴があります。

どういった場合アンカーリンクがずれるかというと、要素の増減をJavaScriptで操作した時です。

時間軸で説明するとこうです。

1.アンカーリンクをクリック

2.別ページのhtmlを読み込む

3.アンカーリンクが発動してスクロール位置を合わせる

4.Jsが発動して要素の増減を操作したため、それより下の要素にスクロール位置を合わせようとした場合、位置がずれる


自分の場合4はカルーセルでした。カルーセルは動き的に3枚の画像を縦に並べてその後JSで横並びにするためその差分がずれました。

ヘッダー固定などでもこの現象は起きるようです。

対応策

JSの時点でずれるためその後のJSで調整しました。

  $(window).on('load', function() {
    var hash = window.location.hash;
    var position = $(hash).offset().top;
    function scroll(position){
      $('html, body').animate({
        scrollTop : position
      }, 100);
    }
    scroll(position);
  });

window.location.hashでurlの#~の部分が取得できます。
多少ずれてから位置が戻る動きにはなってしまいますが、現象も限定的ではあるのでさほど問題ではないかと思います。

またif文でTOPだけなど影響範囲を検討することも大事かと思います。

【JQuery】特定の要素以外の要素を取得

特定の属性以外の要素を取得するのは簡単でやり方は何個かあります。

セレクタで絞る

属性!=値で特定の属性以外の要素を取得するができます。

<ul>
<li>texttext</li>
<li>texttext</li>
<li class="third">texttext</li>
<li>texttext</li>
</ul>
$('li[class!="third"]').css('color', 'red');

.notメソッドを使用する

<ul>
<li>texttext</li>
<li>texttext</li>
<li class="third">texttext</li>
<li>texttext</li>
</ul>
$('.b li').not('.third').css('color', 'red');

.hasメソッドを使用する

.hasは逆に特定の子要素を持つ親要素を取得します。

<ul>
<li><span>texttext</span></li>
<li><span>texttext</span></li>
<li>texttext</li>
<li><span>texttext</span></li>
</ul>
$('.c li').has('span').css('color', 'red');

.hasメソッドを打ち消す

.hasメソッドを応用して特定の要素以外の要素を取得したいと思います。

<ul>
<li><span>texttext</span></li>
<li><span>texttext</span></li>
<li>texttext</li>
<li><span>texttext</span></li>
</ul>
$('.d li:not(:has(">span"))').css('color', 'red');

やり方は様々です。
htmlに合わせて使い分けると良いかと思います。

DEMO

See the Pen ryXVvP by funclur (@funclur) on CodePen.

擬似要素:hoverはないがhover:擬似要素はある

::beforeの:hoverはないが:hoverの::beforeはあります。
同じように::afterの:hoverはないが:hoverの::afterはあります。

下記に例を示します。

リンクにマウスオーバーした際、カラーを変更するデザインがあったとします。
それはa:hoverで色を変えればよいですが、矢印アイコンも変えなければいけないとき、擬似要素であるアイコンにhover効果を充てます。

:hover+::after

See the Pen evaXLg by funclur (@funclur) on CodePen.


a {
	color: blue;
	position: relative;
}
a::hover {
	color: red;
}
a::after {
    position: absolute;
    top: 5px;
    right: -10px;
    left: auto;
    display: block;
    width: 4px;
    height: 4px;
    border-top: 2px solid blue;
    border-right: 2px solid blue;
    content: "";
    -webkit-transform: rotate(45deg);
    -ms-transform: rotate(45deg);
    transform: rotate(45deg);

}
a:hover::after {
    border-top: 2px solid red;
    border-right: 2px solid red;
}

:first-child+::before

これはやったことありませんでしたが実験的にやってみたらやはりできるようです。
最初の要素の擬似要素を指定します。

See the Pen aJrMaL by funclur (@funclur) on CodePen.


ul li {
	margin-top: 5px;
	position: relative;
	padding-left: 21px;
	list-style-type: none;
}
ul li::before {
	position: absolute;
	top: 7px;
	content: "";
	background: #000;
	border-radius: 50%;
	width: 3px;
	height: 3px;
	left: 7px;
}
ul li:first-child::before {
	background: red;
}

擬似クラスと擬似要素の違い

他人様のサイトからお借りします。
https://wp.yat-net.com/?p=4505

擬似クラス
:link
:visited
:active
:hover
:focus
:lang
:target
:root
:nth-child
:nth-last-child
:nth-of-type
:nth-last-of-type
:first-child
:last-child
:first-of-type
:last-of-type
:only-child
:only-of-type
:empty
:not
:enabled
:checked
擬似要素
::before
::after
::first-letter
::first-line
::selection

:hover::after::after:hoverで結構迷うことが多かったのですが、
こうしてみるとcss記述順序としては、
要素+擬似クラス+擬似要素と覚えると良さそうです。
コロンのつく数が増えていくと覚えてもいいですね笑

thunderbirdでメールが送信できない 2017

thunderbirdでメールが送信できない現象が起きました。

https://support.mozilla.org/t5/Basics/Thunderbird-%E3%81%AE%E6%9B%B4%E6%96%B0/ta-p/19555

現象が起こる前にアップデートしたため、もしかしたらと思いましたが
やはり原因はそれだったようです。

augustdesign.info


こちらの記事の通り

Check and Sendを削除したところ送信ができるようになりました。

thunderbirdを開いてツール→アドオン→拡張機能→Check and Send削除(無効化では改善されませんでした)


ただCheck and Sendを削除してしまうと、送信した後に本当に送信していいですか?
という確認のアラートがなくなってしまいます。

この確認に助けられたことが何度かあるので、使えないことは残念ですがしばらくこのまま様子を見ようと思います。

【JavaScript】配列のアルファベットや数値を昇順・降順にソートする 

アルファベット順にソートする

アルファベット順にソートするのは簡単です。
配列にsortメソッドを使用します。

var x = ['tokyo', 'osaka', 'sendai', 'fukuoka'];
x.sort();
console.log(x);

See the Pen yMwWVd by funclur (@funclur) on CodePen.


数値順にソートする

sortメソッドでソートできるのは、アルファベット、ひらがな、カタカナ、数値です。コンピューターは漢字の読み方がわからないので、漢字はソートできないのです。
漢字をソートする場合読み方もデータが必要になります。

また数値も2ケタ、3ケタで評価されません。例えば

var x = [3, 153, 45, 7];
をソートした場合、
[153, 3, 45, 7]となります。

これは先頭文字を比較し、先頭文字が同一であれば2文字目で比較するという処理の特性です。

2ケタ以上の場合

2ケタ以上の場合どうするかですが、sortメソッドにコールバック関数を与えます。

See the Pen oZVRPo by funclur (@funclur) on CodePen.

aとbを比較しbが大きければ-1、aが大きければ1を、同じ値であれば0を返します。

降順

降順は返す値(1, -1)を逆にすれば、結果が得られます。

reverseメソッド

配列の順番を逆にするメソッドが.reverse()です。
配列.reverse()で配列順序が逆になるので便利ですね。