WEBサイト制作の勉強

WEBサイト制作の勉強の為の解説ブログです。

css3を使ったドロワーメニュー

右端から出てくるドロワーメニュー

index.html

<!doctype html>
<html lang="ja">
<head>
<meta charset="utf-8">
<title>ドロワーメニュー</title>
<meta name="viewport" content="width=device-width">
<link rel="stylesheet" href="style.css">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.2.4/jquery.min.js"></script>
<script>
$(function(){
 $('#btn').on('click',function(){
  $('#g-nav').toggleClass('slide');
  $(this).toggleClass('click');
 });
});
</script>
</head>

<body>
<header>
<div class="header-inner">
<h1>タイトル</h1>
<p id="btn"><span></span></p>
<nav id="g-nav">
<ul>
<li><a href="#">ボタン1</a></li>
<li><a href="#">ボタン2</a></li>
<li><a href="#">ボタン3</a></li>
</ul>
</nav>
</div>
</header>
<main>
</main>
</body>
</html>

スタイルシート

@charset "utf-8";
/* CSS Document */

html,body,h1,p,ul,li {
  margin:0;
  padding:0;
  line-height:1.0;
}
ul {
  list-style:none;
}
a {
  text-decoration:none;
}
header {
  background:#4B4949;
  width:100%;
  height:80px;
  padding:10px 0;
  box-sizing:border-box;
}
.header-inner {
  max-width:1200px;
  margin:0 auto;
  display:flex;
  justify-content:space-between;
}
h1 {
  color:#FFFFFF;
  line-height:60px;
  padding-left:20px;
}
#g-nav {
  width:50%;
  background:#C71215;
}
#g-nav ul {
  display:flex;
}
#g-nav li {
  width:33.33%;
  height:60px;
}
#g-nav li a {
  display:block;
  line-height:60px;
  text-align:center;
  color:#FFF;
}
main {
  width:100%;
  height:calc(100vh - 80px);
  background:url(img/01.png) no-repeat center center/cover;
}
#btn {
  display:none;
}
@media screen and (max-width:767px){
 body {
   overflow-x:hidden;
 }
#g-nav {
  width:100%;
  height:calc(100vh - 80px);
  background:rgba(191,27,30,0.40);
  position: fixed;
  top:80px;
  left:100%;
  transition:0.3s;
}
#g-nav.slide {
  left:0;
}
#btn {
  display:block;
  width:60px;
  height:60px;
  margin-right:10px;
  position:relative;
}
#btn span {
  display:block;
  width:40px;
  height:2px;
  background:#FFF;
  position:absolute;
  top:0;
  right:0;
  bottom:18px;
  left:0;
  margin:auto;
  transition:0.1s;
}
#btn span:after {
  display:block;
  content:"";
  width:40px;
  height:2px;
  background:#FFF;
  position:absolute;
  top:36px;
  right:0;
  bottom:0;
  left:0;
  margin:auto;
   transition:0.1s;
}
#btn.click span {
  bottom:0;
  transform:rotate(-45deg);
}
#btn.click span:after {
  top:0;
 transform:rotate(-270deg);
}
#g-nav ul {
  display:flex;
  flex-direction:column;
  margin-left:30%;
  width:70%;
  box-sizing:border-box;
  height:calc(100vh - 80px);
   background:rgba(0,0,0,0.60);
}
#g-nav li {
  width:100%;
  height:60px;
  border-bottom:1px solid #FFF;
}
#g-nav li a {
  display:block;
  line-height:60px;
  padding-left:20px;
  box-sizing:border-box;
  text-align:left;
  color:#FFF;
}
}

jQueryを記述する上で気をつける点

jQueryはライブラリーという性質上、どうしても動作が重くなってしまいます。PCではあまり気にならなくても、パフォーマンスの低いスマートフォンでは読み込み速度が遅くなる、という事が良くあります。
jQueryを適切に記述する事である程度の改善は出来るので、しっかりと覚えましょう。


セレクターの指定はID

やむを得ずクラス名で指定しなければいけない場合以外は必ず「ID名」を指定しましょう。


同じIDでの指定でも
OK

$("#target").css({'color':'red'});

NG

$("div#target").css({'color':'red'});

同じセレクタは変数化する

OK

var target = $('.target p');
target.css({'background-color':'red'});
target.show();


NG

$('.target p').css({'background-color':'red'});
$('.target p').show();

連続した処理はメソッドチェーンを使う

$('#target p').css({'background-color':'red'}).show();

ファイルデータの大きいjQuery本体をCDNにする事で実際には色々なメリットがあります。

メリット

  • 高速化
  • 他サイトでのキャッシュが期待できる(※)
  • 自サーバーにJQueryを置く必要がない


などですが、
一方、万が一CDNがダウンしてしまった場合などには使えなくなってしまいます。このようなトラブルが起こったときに代替策として、フォールバックという方法があります。

<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
<!-- CDNが使えない場合は自サーバーに置いたjQueryファイルを読み込む -->
<script>
window.jQuery || document.write('<script src="js/jquery-3.2.1.min.js"><\/script>');
</script>

jQuery演習問題

  • 「変更」ボタンを押したら、既存のh1要素内のテキストが変更されるよう記さい。

     変更前 クリック前    変更後 クリック後

  • 「変更」ボタンを押したら「on」と「off」が繰り返し、交互に変更されるよう記述し問なさい。
  • 「変更」ボタンを押したら、jQueryCSSメソッドを使い、背景色青で200px正方形のdiv要素を200x400px、背景色緑の長方形に変更させなさい。

  

  • 300pxの正方形を作り、「表示」ボタンを押したら0.5秒かけて フェードしながら表示するように記述しなさい。
  • 「移動」ボタンを押したら、300pxの正方形がx方向に300px移動した後に y方向に100px、アニメーションで移動するように記述しなさい。
  • 「変更」ボタンを押したら、表示されている画像が別の画像が変わり、 alt属性も画像に合った内容に変わるように記述しなさい。
  • 「変更」ボタンを押したら、200pxの正方形と200pxの正円が交互に1秒かけて変形させなさい。変形の指定はcssのtranstionで行うこと。

Instagram API を使ってインスタグラムの画像をサイトに表示させる

f:id:yachin29:20180507003845j:plain


最近はwebサイト上にインスタグラムに投稿した画像を表示しているサイトも珍しくなくなってきました。
ここではInstagram API を使ってインスタグラムのデータをhtmlファイルに埋め込む方法を説明していきます。

Instagram APIを使って出来る事・出来ない事

2018年4月4日にInstagram API の仕様が大幅に変更されました。
今までは、Sandboxというモードを使うことによって、他のユーザーの承認を得られることができれば、限定的にではありますが、他のユーザーの写真を取得することができるようになっていました。しかし、これは2018年4月4日をもって一切できなくなったようです。
なので、クライアントの画像を取得する場合、下記で説明している[CLIENT-ID]と[REDIRECT-URI]をクライアントのアカウントで作成する必要があります。
さらに、2020年には現在のAPIが全て廃止され、自身のアカウントでさえ現在のInstagram APIを使ってWebサイトに表示させる事は完全にできなくなります。
Instagramではこれにとって代わり、ビジネスアカウント向けのInstagram Graph APIというものを充実させていくようです。Facebookでも以前似たような仕様変更がありました。

今後Instagramの写真をWebサイトで表示したい場合はどのしたらいいか

今の所、2020年にInstagram APIが仕様廃止になってしまう予定ですが、場合によっては予定が早まる事も十分考えられます。
ですので、今後Instagramの写真をWebサイトで表示したい・扱いたい場合は、個人的には、「Instagramページへのリンクを貼ったアイコンやテキストをWebサイトに表示する」程度に納めることが無難ではないかと思います。

Sandboxモード

実はInstagramAPIは開発者登録さえすれば自由に使える、というものではありません。
登録したばかりのアプリは「Sandbox Mode(サンドボックスモード)」という状態で動作するのですが、Sandbox Modeでは例えば他のユーザーのデータを自由に取得することはできないなどの制限があります。
この制限を外す、言い換えると別の権限を付加するには、InstagramのReview(審査)が必要です。
ただし、このReviewを通るにはかなり時間がかかってしまいます。



arrown-blog.com





投稿記事を表示させる場合

インスタグラムの個別の投稿記事を埋め込む場合は非常に簡単で、埋め込みたい記事に行き、記事の右下に「・・・」のマークがあるので、そこをクリックします。そして出てきた埋め込みコードをhtmlの任意の場所に貼るだけです。
埋め込みコード内にスタイルが直接埋め込まれている為、自身のcssを効かせたい場合は注意が必要ですが、作業自体は非常に簡単です。またこの方法であれば、基本的には芸能人など誰のアカウントでも表示させる事が可能です。





タイムライン形式で画像を表示させる場合

個別の記事では無く、最新の投稿画像10件(タイムライン)などを表示させたい場合はInstagram API を使用する必要があります。Instagram API を使用する場合、Instagram API の登録やトークンの取得、json形式のデータの取得など、設定しなければいけない事が多くあります。


Instagram API の登録

まずは下記のページからAPIの登録をします。[Register a New Client]ボタンをクリックし、必要な情報を記入し登録します。
https://www.instagram.com/developer/
f:id:yachin29:20180507005647p:plain


登録に必要な情報
  • [Application Name]任意で構いません
  • [Description]任意で構いません。
  • Website URL]開発者のホームページを入力します。APIの使用するドメインである必要はありませんが、認証後にトークンを取得する為に必要です。
  • [Contact email]連絡用メールアドレス

登録が終わると「CLIENT ID」が発行されます。
f:id:yachin29:20180507005445p:plain


アクセストークンの取得

次に登録したAPIの認証作業を行います。

以下のURLの[CLIENT-ID]と[REDIRECT-URI]を先ほど登録したアプリの情報に置き換えて、アクセスすることで認証が可能です。[REDIRECT-URI]は登録時に設定した[Website URL]と同じです。

https://api.instagram.com/oauth/authorize/?client_id=CLIENT-ID&redirect_uri=REDIRECT-URI&response_type=token

[CLIENT-ID]と[REDIRECT-URI]を置き換えてアクセスすると、[Website URL]で登録したURLに飛びますが、そのURLのパラメータにアクセストークンが付与されています。そのトークンはあとで必要になるので必ず保存しておきましょう。

f:id:yachin29:20180507012232p:plain

APIデータの取得

先ほど取得したアクセストークンを使ってInstagram APIを取得してみましょう。アクセスするとjson形式でデータが確認できます。あとはこのデータをJavaScriptPHPなどで処理すればOKです。
以下のURLの「ACCESS-TOKEN」部分を先ほど取得したアクセストークンの数値と置き換えましょう。

https://api.instagram.com/v1/users/self/media/recent/?access_token=ACCESS-TOKEN

詳しい解説はこちらのサイトに記載されています。スライド付きで非常に解り易いです。
capotast.co.jp



Instagram APIjsonデータを使い、画像を表示させる

JavaScriptだけで表示させる事も可能ですが、「アクセストークン」などの情報が表示されてしまう為PHPを使って表示させます。
今回は「アクセストークン」部分のみphpにし、表示部分はJavascriptで行います。
また、表示させる情報は画像と「いいね」の数の2つのみにします。

f:id:yachin29:20180507042543p:plain



index.htmlではulだけ設置し、中のliはjsで生成します。

<!DOCTYPE html>
<html lang="ja">
<head>
  <meta charset="utf-8">
  <title>Instagtam API テスト</title>
  <link href="//netdna.bootstrapcdn.com/font-awesome/4.0.3/css/font-awesome.min.css" rel="stylesheet">
  <link rel="stylesheet" href="insta.css">
  <script src="https://code.jquery.com/jquery.min.js"></script>
  <script src="insta.js"></script>
</head>
<body>
  <h1><i class="fa fa-instagram fa-fw"></i>Instagtam APIテスト</h1>
  <ul class="instagram"></ul>
</body>
</html>


insta.js

$(function(){
    var $container = $(".instagram");
    var html = "";

    $.ajax({
        url: "insta.php",//PHPファイルURL
        type:"POST",
        dataType: "json"
    })
    
    
    .done(function(data){
        //通信成功時の処理
        $.each(data.data,function(i,item){
            var imgurl = item.images.low_resolution.url; //低解像度の画像のURLを取得
            var link = item.link; //リンクを取得
            var like = item.likes.count;//いいねの数
            html += '<li><a href="' + link + '"target="_blank"><img src="' + imgurl + '"></a><p class="ins_like"><i class="fa fa-heart" aria-hidden="true"></i>' + like + '</p></li>';
        });
    }).fail(function(){
        //通信失敗時の処理
        html = "<li>画像を取得できません。</li>";
    }).always(function(){
        //通信完了時の処理
        $container.html(html);
    });
});

「アクセストークン」のような重要なデータは他人に見られないようにphpファイルに分け、ajaxを使ってjsファイルで読み込みます。
insta.php

<?php
//POSTリクエストの場合のみ受付
if($_SERVER['REQUEST_METHOD'] == 'POST'){
    //アクセストークン
    $access_token = "ここにアクセストークンが入ります"; //取得したアクセストークンを設置
    $count = 8; //表示件数

    
    //JSONデータを取得して出力
    echo @file_get_contents('https://api.instagram.com/v1/users/self/media/recent/?access_token='.$access_token."&count=".$count);
    //終了
    exit;
}
?>


あとは見た目をcssで整えます。

@charset "UTF-8";
/* CSS Document */

html,body,h1,p,ul,li {
  margin: 0;
  padding: 0;
}
ul {
list-style: none;
}
a {
text-decoration: none;
color: #222;
}
img {
vertical-align: bottom;
}


h1 {
text-align: center;
padding: 20px 0;
}

.instagram {
  width: 1000px;
  margin: 0 auto;
}

.instagram li {
margin: 5px;
  float: left;
  width: 240px;
  height: 240px;
  overflow: hidden;
  position: relative;
}
p.ins_like {
position: absolute;
width: 100%;
height: 40px;
bottom: 0;
left: 0;
background: rgba(255,255,255,0.70);
padding: 10px 20px 10px 0;
box-sizing: border-box;
text-align: right;
}
.instagram li img {
max-width: 100%;
}
.fa-heart {
margin-right: 10px;
color: #EA4E50;
}


もっと細かいデータ取得を行いたい場合はphpで各パロメータを取得する必要があります。各パロメータの取得方法は以下のサイトを参考に。
qiita.com




「SnapWidget」のようなツールを使う事で、簡単にタイムラインを埋め込みが出来ますが、無料版は色々と制限があります。
snapwidget.com

TwitterやFacebookなどのSNSをサイトに埋め込む

Webサイト上で新着情報や更新頻度の高い情報を表示させたい時には、TwitterFacebookなど既存のSNSプラグインを使うのが非常に便利です。

SNSプラグインを使用すれば、わざわざHTML内のデータを触る事無く、SNSに記事を投稿するだけでWebサイト内の情報が更新されます。クライアントにHTMLの知識が無い場合でも、前回の授業で紹介したGoogleカレンダーSNSプラグインを上手く使って、更新頻度の高いサイト作りを目指しましょう。

Twitter

Twitterのタイムラインを埋め込みます。タイムラインにも数種類ありますが、今回は一番シンプルな物を埋め込んでみましょう。Twitterの場合、公開されているものであれば、どのユーザーのタイムラインでも埋め込むことができます。非常に簡単に出来るので、積極的に使っていきましょう。


f:id:yachin29:20150318191943p:plain


ウジェット制作画面
https://publish.twitter.com/#

ウジェット制作画面で生成されるコードはそのままではローカル環境で確認する事が出来ません。
ローカルでウジェットを確認する場合はエンベットされているjavascriptのアドレスの頭に「https:」を付け加えましょう。

最初にコピーしてきたコード

<a class="twitter-timeline" href="https://twitter.com/seiburailway">Tweets by seiburailway</a> <script async src="//platform.twitter.com/widgets.js" charset="utf-8"></script>

                  ↓

https:」を付け加える

<a class="twitter-timeline" href="https://twitter.com/seiburailway">Tweets by seiburailway</a> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

httpやhttpsを省略する

CSSJavascriptを読み込むときhttpやhttpsを省略する事が出来ます。この形であれば、リンク先が「http」のページから「https」のページに変更してもリンク先へのアドレスをわざわざ書き換える必要が無くなります。最近は大規模サイトのみならず小規模サイトでも「https」になっている場合が良くあるので、省略しておくと便利です。
ただ、この場合ローカルでは表示されない為、注意が必要です


Facebook

2015年6月にFacebookプラグイン機能が大幅に仕様変更してしまい、これまでの「Like Box」も2015年6月以降使う事が出来なくなってしまいました。今後は「Page Plugin」というプラグインを「Like Box」の代わりに使っていく事になります。


yachin29.hatenablog.com



Facebookの方もTwitterと同じようにプラグインを使用するのですが注意が必要です。Facebookの場合、個人のページでは出来ず、Facebookページ(旧ファンページ)のみがWebサイトに埋め込む事が出来ます。
なのでFacebookの場合、クライアントがFacebookのアカウントを持っていない場合、Facebookページを作成する所から始まります。


https://www.facebook.com/pages/create/

f:id:yachin29:20150318193353p:plain



Facebookページを作成したら、開発者ツールから埋め込みたいウジェットを選択し、コードをコピーしHTMLに貼り付ければOKです。ただFacebookの場合、サーバー環境上で無いとデータが表示されないのでXamppなどを使って確認してみましょう。

ページプラグイン - ソーシャルプラグイン - ドキュメンテーション - 開発者向けFacebook



facebookの場合、開発者メニューが英語表記なので、判らない場合は下記のサイトなどを参考にしてみて下さい。


smmlab.jp


www.qam-web.com

jQueryでのパララックス

パララックスとは、視差効果のことです。
Webデザインにおけるパララックスはスクロールなどの動作に応じて、複数のレイヤー(層)にある要素を異なるスピードで動かすことで、「立体感や奥行きを演出」、「フェード・拡大縮小・回転などの視覚的エフェクト」を演出する手法を指します。




最近は一時期よりは減りましたが、シングルページの縦長ページではまだまだ見かけるデザインです。
シングルページはページデザインが単調になりがちなので、パララックスやスクロールアニメーションを使って、アイキャッチを作りましょう。


pogg-sweetpotatopie.com




on-ze.com


<!doctype html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<title></title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="robots" content="noindex">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.2.4/jquery.min.js"></script>
<script src="js/script.js"></script>
</head>

<body>
<div class="parallax para-box" data-height="70vh" data-speed="0.8" data-mobile="false">
<div class="para_img background"></div>
</div><!--/#para-box-->

<div class="parallax para-box" data-height="70vh" data-speed="0.8" data-mobile="false">
<div class="para_img background"></div>
</div><!--/#para-box-->

<div class="parallax para-box" data-height="70vh" data-speed="0.8" data-mobile="false">
<div class="para_img background"></div>
</div><!--/#para-box-->

<div class="parallax para-box" data-height="70vh" data-speed="0.8" data-mobile="false">
<div class="para_img background"></div>
</div><!--/#para-box-->

<div class="parallax para-box" data-height="70vh" data-speed="0.8" data-mobile="false">
<div class="para_img background"></div>
</div><!--/#para-box-->
</div>

<script src="js/parlx.js"></script>
<script>
$('.parallax').Parlx({
item: '.background',
});
</script>
</body>
</html>


スタイルシート

.parallax {
	position:relative;
	height:80vh;
	overflow:hidden;
}
.background {
	position:absolute;
	background-repeat:no-repeat;
	background-size:cover;
}

jquery

/*!
* parlx.js v1.0
* Copyright 2017-2018 Jakub Biesiada
* MIT License
*/

class Parlx {
  constructor(elements, settings = {}) {
    if (elements.length > 1) {
      this.init(elements, settings);
      return;
    } else {
      this.element = elements;
    }

    this.settings = this.settings(settings);

    this.parallaxEffect();
    this.addEventListeners();
  }

  init(elements, settings) {
    for (var element = 0; element < elements.length; element++) {
      new Parlx(elements[element], settings);
    }
  }

  addEventListeners() {
    window.addEventListener('scroll', () => this.onWindowScroll());
    window.addEventListener('resize', () => this.onWindowResize());
  }

  onWindowScroll() {
    this.parallaxEffect();
  }

  onWindowResize() {
    this.parallaxEffect();
  }

  parallaxEffect() {
    if ("ontouchstart" in document.documentElement && this.settings.mobile === false) {
      this.settings.speed = 0;
    }

    if (this.settings.speed < 0 || this.settings.speed > 0.5) {
      this.settings.speed = 0.3;
    }

    this.element.style.height = this.settings.height;

    this.children = this.element.querySelector(this.settings.item);

    let scrolled = window.pageYOffset - this.element.offsetTop;

    Object.assign(this.children.style, {
      'top': '0px',
      'left': '50%',
      'min-height': `${this.element.offsetHeight * (1 + this.settings.speed * 2)}px`,
      'min-width': '100%',
      'width': 'auto',
      '-webkit-transform': `translate(-50%, ${this.settings.speed * scrolled}px)`,
      '-ms-transform': `translate(-50%, ${this.settings.speed * scrolled}px)`,
      'transform': `translate(-50%, ${this.settings.speed * scrolled}px)`
    });

    if (this.children.tagName.toLowerCase() !== 'img') {
      this.children.style.backgroundPosition = 'center center';
    }
  }

  settings(settings) {
    let defaults = {
      item: '.background',
      speed: 0.3,
      height: '400px',
      mobile: true
    }

    let custom = {};

    for (var setting in defaults) {
      if (setting in settings) {
        custom[setting] = settings[setting];
      } else if (this.element.getAttribute(`data-${setting}`)) {
        let attribute = this.element.getAttribute(`data-${setting}`);
        try {
          custom[setting] = JSON.parse(attribute);
        } catch (e) {
          custom[setting] = attribute;
        }
      } else {
        custom[setting] = defaults[setting];
      }
    }

    return custom;
  }
}

// JQUERY PLUGIN CALL IF JQUERY LOADED
if (window.jQuery) {
  let $ = window.jQuery;

  $.fn.Parlx = function (options) {
    for (var element = 0; element < this.length; element++) {
      new Parlx(this[element], options);
    }
  }
}

jQueryでのパララックス

パララックスとは、視差効果のことです。
Webデザインにおけるパララックスはスクロールなどの動作に応じて、複数のレイヤー(層)にある要素を異なるスピードで動かすことで、「立体感や奥行きを演出」、「フェード・拡大縮小・回転などの視覚的エフェクト」を演出する手法を指します。




最近は一時期よりは減りましたが、シングルページの縦長ページではまだまだ見かけるデザインです。
シングルページはページデザインが単調になりがちなので、パララックスやスクロールアニメーションを使って、アイキャッチを作りましょう。


pogg-sweetpotatopie.com




on-ze.com


<!doctype html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<title></title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="robots" content="noindex">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.2.4/jquery.min.js"></script>
<script src="js/script.js"></script>
</head>

<body>
<div class="parallax para-box" data-height="70vh" data-speed="0.8" data-mobile="false">
<div class="para_img background"></div>
</div><!--/#para-box-->

<div class="parallax para-box" data-height="70vh" data-speed="0.8" data-mobile="false">
<div class="para_img background"></div>
</div><!--/#para-box-->

<div class="parallax para-box" data-height="70vh" data-speed="0.8" data-mobile="false">
<div class="para_img background"></div>
</div><!--/#para-box-->

<div class="parallax para-box" data-height="70vh" data-speed="0.8" data-mobile="false">
<div class="para_img background"></div>
</div><!--/#para-box-->

<div class="parallax para-box" data-height="70vh" data-speed="0.8" data-mobile="false">
<div class="para_img background"></div>
</div><!--/#para-box-->
</div>

<script src="js/parlx.js"></script>
<script>
$('.parallax').Parlx({
item: '.background',
});
</script>
</body>
</html>


スタイルシート

.parallax {
	position:relative;
	height:80vh;
	overflow:hidden;
}
.background {
	position:absolute;
	background-repeat:no-repeat;
	background-size:cover;
}

jquery

/*!
* parlx.js v1.0
* Copyright 2017-2018 Jakub Biesiada
* MIT License
*/

class Parlx {
  constructor(elements, settings = {}) {
    if (elements.length > 1) {
      this.init(elements, settings);
      return;
    } else {
      this.element = elements;
    }

    this.settings = this.settings(settings);

    this.parallaxEffect();
    this.addEventListeners();
  }

  init(elements, settings) {
    for (var element = 0; element < elements.length; element++) {
      new Parlx(elements[element], settings);
    }
  }

  addEventListeners() {
    window.addEventListener('scroll', () => this.onWindowScroll());
    window.addEventListener('resize', () => this.onWindowResize());
  }

  onWindowScroll() {
    this.parallaxEffect();
  }

  onWindowResize() {
    this.parallaxEffect();
  }

  parallaxEffect() {
    if ("ontouchstart" in document.documentElement && this.settings.mobile === false) {
      this.settings.speed = 0;
    }

    if (this.settings.speed < 0 || this.settings.speed > 0.5) {
      this.settings.speed = 0.3;
    }

    this.element.style.height = this.settings.height;

    this.children = this.element.querySelector(this.settings.item);

    let scrolled = window.pageYOffset - this.element.offsetTop;

    Object.assign(this.children.style, {
      'top': '0px',
      'left': '50%',
      'min-height': `${this.element.offsetHeight * (1 + this.settings.speed * 2)}px`,
      'min-width': '100%',
      'width': 'auto',
      '-webkit-transform': `translate(-50%, ${this.settings.speed * scrolled}px)`,
      '-ms-transform': `translate(-50%, ${this.settings.speed * scrolled}px)`,
      'transform': `translate(-50%, ${this.settings.speed * scrolled}px)`
    });

    if (this.children.tagName.toLowerCase() !== 'img') {
      this.children.style.backgroundPosition = 'center center';
    }
  }

  settings(settings) {
    let defaults = {
      item: '.background',
      speed: 0.3,
      height: '400px',
      mobile: true
    }

    let custom = {};

    for (var setting in defaults) {
      if (setting in settings) {
        custom[setting] = settings[setting];
      } else if (this.element.getAttribute(`data-${setting}`)) {
        let attribute = this.element.getAttribute(`data-${setting}`);
        try {
          custom[setting] = JSON.parse(attribute);
        } catch (e) {
          custom[setting] = attribute;
        }
      } else {
        custom[setting] = defaults[setting];
      }
    }

    return custom;
  }
}

// JQUERY PLUGIN CALL IF JQUERY LOADED
if (window.jQuery) {
  let $ = window.jQuery;

  $.fn.Parlx = function (options) {
    for (var element = 0; element < this.length; element++) {
      new Parlx(this[element], options);
    }
  }
}