20200426のJavaScriptに関する記事は30件です。

学習記録 #2 モーダル実装

行ったこと

- HTML / CSS / JavaScript
- サービス作成

つまずいたこと

- モーダルの実装

HTML

      <!-- モーダル -->
      <div id="modal">
        <div class="modal-content">
          <div class="modal-body">
            <h1>hello</h1>
            <button id="closeButton">Close</button>
          </div>
        </div>
      </div>
      <!-- モーダル表示用ボタン -->
      <button id="openButton">Open Modal</button>

CSS

#modal{
display: none;
position: fixed;
z-index: 1;
left: 0;
top: 0;
height: 100%;
width: 100%;
overflow: auto;
background-color: rgba(0,0,0,0.5);
}

.modal-content{
background-color: white;
width: 500px;
margin: 15% auto;
}

JavaScript

const modal = document.getElementById('modal');
const openButton = document.getElementById('openButton');
const closeButton = document.getElementById('closeButton');


openButton.addEventListener('click', () => {
  modal.style.display = 'block';
});

closeButton.addEventListener('click', () => {
  modal.style.display = 'none';
});

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Herokuへのアップロードでつまづいた時の対処法 Node.js + MongoDB

自分の経験をここに記述します。

【経緯】先日、EJS, CSS, JavaScript, MongoDB, Nodeを使って作成したWebsiteをHerokuにアップロードしようと試みた時、正常にアップロードできず、丸2日間の時間を犠牲にした上でようやく問題解決までに至りました。ここで記載することがいつかこれを見た未来の困っている方々への手助けになればと思います。

【方法】ステップに分けて説明していきます。MongoDBを使用している場合には、別の記事でその追加で必要な方法を記述します。

1:Command Line(Hyper Terminal)がアップロードしようとしているファイルのパスを正しく選択しているか確認する。

2:Command Line(Hyper Terminal)からHerokuへとログインする。
コマンド:$heroku login 

3:GitをInitializeし、add、commitする。以下順々にコマンドを実行する。
コマンド:$git init  

コマンド:$git add .

コマンド:$git commit -m "sample message"

4:HerokuでURLを作成する。 
コマンド(urlが何でもいい場合):$heroku create  
コマンド(自分のオリジナルを作成する場合):$heroku create ここに半角英数でタイプする。但し他ユーザーがすでに使用している場合は、そのurlは使えない。

5:Gitにpushをする。 
コマンド:$git push heroku master

6:現状では正しくHerokuへとアップロードはされません。ほぼ100%エラーの表示がでます。これからそのエラーを直していきましょう。

7:自分のファイル内にprocfileが作成しているか、確認する。procfileが何か分からない場合はこの方の記事を参考にしてみてください。 https://creepfablic.site/2019/06/15/heroku-procfile-matome/

8:procfileの中身が正しく記載されているか確認する。私の場合、web: node app.js、app.jsはあくまでも私がよく使うファイル名のためindex.jsや他のファイル名の場合はそちらに書き換えてください。

9:app.listen(process.env.PORT || 3000, function( ){

console.log("The server 3000 is now up and runnning")

});

私の場合、app.jsの中にローカルサーバーを立ち上げるためのapp.listenを入力しているので、そこにprocess.env.PORTと追加されているか確認する。

10:再度、Command Line(Hyper Terminal)の画面に戻る。そして自分のファイルへのパスが選択されている状態で、次のコマンドを入力する。コマンド:$heroku buildpacks

そのコマンドを入力した時にheroku/nodejsと表示されていれば特に何もしなくて良い。しかし、何も表示されない、もしくは別のものが表示された場合には次のコマンドを入力する。
コマンド:$heroku buildpacks:set heroku/nodejs

11:もう一度、コマンド:$heroku buildpacksを入力して正しくheroku/nodejsと表示されるか確認する。

12:自分のパソコンにインストールされているNodeとNpmが最新版であるか確認する。どこでインストールするか分からない場合は? https://nodejs.org/ja/ で推奨版をダウンロードする。左のバージョン。

コマンド:$node --version  

コマンド: $npm --version

13:自分のファイルの中にpackage-lock.jsonというファイルが作られているか確認する。作成されていない場合は次のコマンドを入力する。
コマンド:$npm install

14:package-lock.jsonの中に以下のプログラムが記載されているか確認する。されていない場合は順番はどこでもいいのでファイル内に付け加える。NodeとNpmのバージョンは2020/04時点のものなので、最新かどうかは?https://nodejs.org/ja/  
で確認する。右側の最新版のバージョンをnodeに記述する。最後のxの部分は変更しなくて大丈夫。scriptsのapp.jsはあくまでも私が使用しているファイル名なので、これは各個人のファイル名に直す。

"engines": {
"node": "^14.0.x",
"npm": "6.14.x"
}

"scripts": {
"start": "node app.js"
}

15:.gitignoreファイルが作成しているか、確認する。まず次のコマンドを入力する。

コマンド:$git ls-files | grep node_modules

もしも、上記のコマンドを入力した際にリストがズラーーーっと表示された場合は以下のコマンドを順々に入力する。表示されなかった場合は多分.gitignoreが作成されていると思う。

コマンド:$echo "node_modules" >> .gitignore

コマンド:$git rm -r --cached node_modules

コマンド:$git commit -am 'untracked node_modules'

16:再度、.gitignoreが作成されているか、コマンド:$git ls-files | grep node_modules、を入力して確認する。自分のファイル内で.gitignoreというファイルが作成されているのを確認できればおっけい。

17:.gitignoreの中にnode_modulesと記載されていると思うので、その下に以下のコマンドを入力する。

/lib  ←この4文字を記述する。

18:これであとは再度Herokuへのアップロードを試みる。以下の順でCommand Line(Hyper Terminal)内でコマンドを実行する。

コマンド:$heroku login

コマンド:$git init

コマンド:$git add .

コマンド:$git commit -m "whatever you want to type"

コマンド:$git push heroku master

これで正しくHerokuへとアップロードが完了するはずです。

19:最後に、冒頭にも書きましたが、MongoDBを使用している場合はもうワンステップ必要な作業がありますので次回のストーリーを参考にしてみてください。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【Rails】deviseを用いたユーザー新規登録機能の実装(基礎〜少し応用)

はじめに

Ruby on Rails を用いてWEBアプリを作成中です。
ユーザー新規登録の機能を実装するために、「devise」というgemを用いることにしました。
備忘もかねて、本文に実装した内容を残しておきます。
errorで困ったポイントも残しておきますので、参考にしていただけると幸いです^^

専門用語や参考にさせていただいた記事は最後に記載させていただいております。
「これ、なんで記述してるんだろう?」と、私自身が初めて作成した時に感じたポイントでもありますので、
初心者の方は気になるところかとも思います。
そちらも参照していただければと思います。

今回の方法はあくまで一つの実装方法でしかなく、やり方は色々あるのと、
私もまだ未熟なため、わかりにくい記述や余分な記述もございますし、調べきれてない、試しきれてないところもございます。
共にブラッシュアップしていければとも思ってますので、ご指摘もいただければと思います。

記載しきれなかった部分は、随時更新か、別途記事を用意いたします。

実装の目標

今回は以下の画像のような表示を目標として実装しました。
全てを解説するのは大変だったので、「ニックネーム」「メールアドレス」「パスワード」「生年月日」のみに絞っておりますのでご了承ください。
カラムのカスタマイズ、エラー表示、パスワードの表示/非表示、生年月日の選択など、「devise」の基本だけでなく、少し工夫が必要な内容も網羅してるかと思いますので、参考になれば幸いです。
Screenshot from Gyazo
Screenshot from Gyazo

1. deviseのインストール手順

 1-1. Gemfileに追記

(前略)
gem 'devise'
(後略)

※注意
「development、test、production」のgroup内に記述すると特定の環境でのみ使用する設定となりますので、group外に記述するようにしてください。

 1-2. コマンドの実行(インストール)

$ bundle install
$ rails g devise:install

2. Userモデルを作成

インストール後、モデルとテーブルを作成するために、以下をターミナルで実行してください。
通常のモデル作成とはコマンドが違うので注意してください。

$ rails g devise user 

マイグレーションファイルとモデルファイルが出来るので、以下のように記述ください。

2020*****_devise_create_users.rb
class DeviseCreateUsers < ActiveRecord::Migration[5.0]
  def change
    create_table :users do |t|
      t.string :nickname, null: false
      t.string :email, null: false, default: ""
      t.string :password, null: false, default: ""
      t.string :encrypted_password, null: false, default: ""
      t.date :birthday, null: false

      # 〜省略〜

    end

    add_index :users, :email, unique: true

    # 〜省略〜

  end
end
app/models/user.rb
class User < ApplicationRecord
  # Include default devise modules. Others available are:
  # :confirmable, :lockable, :timeoutable and :omniauthable
  devise :database_authenticatable, :registerable,
         :recoverable, :rememberable,  :validatable

  VALID_EMAIL_REGEX = /\A[\w+\-.]+@[a-z\d\-.]+\.[a-z]+\z/i
  VALID_PASSWORD_REGEX = /\A(?=.*?[a-z])(?=.*?\d)[a-z\d]+\z/i

  # 〜省略〜

  validates :nickname, presence: true, length: { maximum: 20 }
  validates :email, presence: true, uniqueness: true, format: { with: VALID_EMAIL_REGEX }
  validates :password, presence: true, length: { minimum: 7 }, format: { with: VALID_PASSWORD_REGEX }
  validates :birthday, presence: true

  # 〜省略〜

end

モデル「user.rb」について
「VALID_EMAIL_REGEX」「VALID_PASSWORD_REGEX」は正規表現によって、特定の文字を弾くようにしております。
「presence: true」は記述することで、空で登録することを弾くようにしてます。
「length: { maximum: 20 }」と「length: { minimum: 7 }」は文字数制限です。

ここで、以下の「devise.rb」に記述されてる「config.password_length = 6..128」についても、次のように編集しておきます。
この数字は文字制限を表してます(つまり、minimumが「6」です)。
理由はモデル「user.rb」より、今回passwordは7文字以上としているため、minimumが「7」である必要があります。
また、こちらを編集後はサーバーの再起動をしないと、反映されませんのでご注意を。

「devise.rb」の「config.password_length = 6..128」を編集した理由は、そのままにするとモデル「user.rb」側のバリデーション「length: { minimum: 7 }」と「devise.rb」側のバリデーション「config.password_length = 6..128」が共存することになるため、2つのバリデーションに引っかかって、2つのエラー表示されてしまうからです。
どちらか片方を削除する方法もありかと思いますが、経験もかねて、どちらも残す方法しか試せておりません。

config/initializers/devise.rb
# frozen_string_literal: true

# Use this hook to configure devise mailer, warden hooks and so forth.
# Many of these configuration options can be set straight in your model.
Devise.setup do |config|
  Rails.application.credentials[:secret_key_base]

  # 〜省略〜

  config.password_length = 7..128

  # 〜省略〜

end

最後にmigrationファイルをデータベースに反映するために、以下のコマンドを実行。

$ rails db:migrate

3. コントローラーの編集

Viewなどを先に提示してもよかったのですが、エラー表示などについての説明を一緒にした方が良いと判断し、ルーティングやコントローラーの設定を先に説明いたします。

まずはコントローラーから。
今回はユーザー新規登録(サインアップ/sign_up)の実装についてですので、コントローラーは「application_controller.rb」のみで大丈夫です。
以下のように記載します。

「configure_permitted_parameters」メソッドの定義をしてますが、deviseをインストールすることでdevise_parameter_sanitizerのpermitメソッドが使えるようになります。これがストロングパラメータに該当する機能です。サインアップ時に入力された「nickname、email、password、birthday」のキーの内容の保存を許可しています。

app/controllers/application_controller.rb
class ApplicationController < ActionController::Base
  protect_from_forgery with: :exception
  before_action :configure_permitted_parameters, if: :devise_controller?

  protected

  def configure_permitted_parameters
    added_attrs = [ :nickname, :email, :password, :birthday ]
    devise_parameter_sanitizer.permit :sign_up, keys: added_attrs
  end
end

4. ルーティングの編集

以下のように記載してください。

注意点としては、「routes.rb」の順番です。
「users/:id」が「users/sign_in」を包括してエラーが発生しないように、「devise_for :users」を「resources :users」より先に書く必要があります。

また、deviseでサインアップする際に、例えばパスワードを忘れて保存しようとしてエラーが発生すると、親ページにリダイレクトされます。
つまり、サインアップページ「/users/sign_up」でエラーが発生した場合、「/users」にリダイレクトされてしまいます。
そのまま登録するとルーティングエラーが表示されます。

これを回避するために、「devise_scope :users」以下の記述を追記して、任意のルーティングをさせています。
方法はいくつかありますが、今回は手っ取り早そうです。

config/routes.rb
Rails.application.routes.draw do

  devise_for :users

  devise_scope :users do
    get '/users', to: redirect("/users/sign_up")
  end

  # 〜省略〜

end

5. Veiwの編集

まずは、以下のコマンドを実行してください。Modelに対応するViewが生成されます。
Modelには「users」などを入れる文献が多ので、以下は「$ rails g devise:views users」で実行してます。
私が学んだ某スクールで最初に学んだ時は「devise」でしたので、ユーザーマイページと分けるために、私の場合は「devise」で生成してますが。

$ rails g devise:views Model

※生成されるViewファイル
 app/views/users/confirmations/new.html.erb
 app/views/users/mailer/confirmation_instructions.html.erb
 app/views/users/mailer/password_change.html.erb
 app/views/users/mailer/reset_password_instructions.html.erb
 app/views/users/mailer/unlock_instructions.html.erb
 app/views/users/passwords/edit.html.erb
 app/views/users/passwords/new.html.erb
 app/views/users/registrations/edit.html.erb
 app/views/users/registrations/new.html.erb
 app/views/users/sessions/new.html.erb
 app/views/users/shared/_links.html.erb
 app/views/users/unlocks/new.html.erb

 

 5-1. HTML/HAMLの記述

「registrations/new.html.erb」をユーザー新規登録ページとして編集していきます。
また、以下の通り、HTMLからHAMLに変換して記述してます。

app/views/users/registrations/new.haml.erb
.signup__main
    .signup__main__content
      %h2.signup__main__content__head
        会員情報入力

      = form_for(resource, as: resource_name, url: registration_path(resource_name)) do |f|

     # 〜省略〜

              .field
                .field-label 
                  = f.label 'ニックネーム'
                %span.form-require 必須
                .field-input
                  = f.text_field :nickname, class: "field-input-full", autofocus: true, autocomplete: "nickname", placeholder: "例)メルカリ太郎"
                .input-error
                  = resource.errors.full_messages_for(:nickname)[0]

              .field
                .field-label
                  = f.label 'メールアドレス'
                %span.form-require 必須
                .field-input
                  = f.email_field :email, class: "field-input-full", autofocus: true, autocomplete: "email", placeholder: "PC・携帯どちらでも可"
                .input-error
                  = resource.errors.full_messages_for(:email)[0]

              .field
                .field-label 
                  = f.label :password, 'パスワード'
                  %span.form-require 必須
                .field-input.toggle
                  = f.password_field :password, class: "field-input-full", autocomplete: "off", autocomplete: "password", placeholder: "7文字以上の半角英数字", id:'password'
                  .checkbox-field
                    %input#js-passcheck.checkbox.js-password-toggle{type: "checkbox"}
                    %label.btn-label.js-password-label{for: "js-passcheck"}
                      %i.fas.fa-eye-slash{style: "font-size:20px;color:#808080"}
                .input-error
                  = resource.errors.full_messages_for(:password)[0]
                .field-info
                  ※ 英字と数字の両方を含めて設定してください

              .field
                .field-label 
                  = f.label '生年月日'
                %span.form-require 必須
                .birthday-select
                  = raw sprintf(f.date_select( :birthday, use_two_digit_numbers: true, prompt: "--", start_year: Time.now.year, end_year: 1900, date_separator: '%s'), '年 ', '月 ') + "日"
                .input-error
                  = resource.errors.full_messages_for(:birthday)[0]

     # 〜省略〜

              .actions
                = f.submit "登録", class: 'btn'

 

 5-2. エラー表示

今回のエラー表示は、ActiveRecordのvalidatesでエラーになった時に表示されるメッセージを利用します。
上記のように、バリデーションエラーは「errors.full_messages_for(:attribute_name)」で各attributeのエラーメッセージは取得してます。

なるほど!
ん?「各attribute」って何?

まずは何も考えずに、ネット上から「devise.ja.yml」をダウンロードし、「/config/locales」に保存してください。
次に、「devise.ja.yml」に以下を追記。
ここに追記した、「birthday、nickname、email、password」が「attribute」です。

ついでに、日本語化も実施。
「ja.yml」をネットからダウンロードし、先ほどと同じく「/config/locale/」以下に入れる。
「"%{attribute}%{message}"」とあるように、バリデーションエラーの内容に合わせて、「attribute」と「message」を選択してくれる。

config/locales/devise.ja.yml
ja:
  activerecord:
    attributes:
      user:
        birthday: "生年月日"
        nickname: "ニックネーム"
        email: Eメール
        password: パスワード

   # 〜省略〜
config/locales/ja.yml
 # 〜省略〜

   errors:
     format: "%{attribute}%{message}"
     messages:
       accepted: を受諾してください
       blank: を入力してください

 # 〜省略〜

 

 5-3. パスワードの表示/非表示

「/registrations/new.haml.erb」のパスワード入力は、何もしなければ非表示です。
何かしらのアクションを起こしたら、表示出来るようにしないと、利用者にとってわかりにくかったりします。
今回は、最近よく見る「目のマーク」を押したら表示/非表示を切り替えられるようにjavascriptとSCSSを駆使して表現しました。
参考までに一部コードを提示します。
ポイントとしては、「(password).attr('type','text');」「(password).attr('type','password');」を切り替えることで、「f.password_field」が持ってる「type」を切り替えることができ、表示/非表示を切り替えることができます。

app/views/users/registrations/new.haml.erb
     # 〜省略〜

  .field-input.toggle
    = f.password_field :password, class: "field-input-full", autocomplete: "off", autocomplete: "password", placeholder: "7文字以上の半角英数字", id:'password'
    .checkbox-field
      %input#js-passcheck.checkbox.js-password-toggle{type: "checkbox"}
      %label.btn-label.js-password-label{for: "js-passcheck"}
        %i.fas.fa-eye-slash{style: "font-size:20px;color:#808080"}

     # 〜省略〜
stylesheets/modules/users.scss
    .toggle{ 
      position: relative;
      .checkbox-field{
        position: absolute;
        right: 15px;
        top: 45px;
        .checkbox {
          display: none;
        }
      }
    }
app/assets/javascripts/registrations_new.js
$(function(){
  var password = '#password';
  var passcheck = '#js-passcheck';
  $(passcheck).change(function(){
    const passwordLabel = document.querySelector('.js-password-label');
    if ($(this).prop('checked')){
      $(password).attr('type','text');
      passwordLabel.innerHTML = '<i class="fas fa-eye" style="font-size:20px;color:#808080"></i>';
    } else {
      $(password).attr('type','password');
      passwordLabel.innerHTML = '<i class="fas fa-eye-slash" style="font-size:20px;color:#808080"></i>';
    }
  })
})

 5-4. 生年月日の選択

以下の「new.haml.erb」の通り、「date_selectタグ」という方法を使って実装しました。
超簡単です。

app/views/users/registrations/new.haml.erb
     # 〜省略〜

  .birthday-select
    = raw sprintf(f.date_select( :birthday, use_two_digit_numbers: true, prompt: "--", start_year: Time.now.year, end_year: 1900, date_separator: '%s'), '年 ', '月 ') + "日"

     # 〜省略〜

ですが1点、注意点があります。
バリデーションエラーが発生すると、「field_with_errors」クラスのdivタグが挿入され、「+ "日"」が切り離されてしまい、以下の画像のようにズレてしまいます。
Screenshot from Gyazo

【バリデーションエラー発生時】app/views/users/registrations/new.haml.erb
     # 〜省略〜

  .birthday-select
    = raw sprintf(f.date_select( :birthday, use_two_digit_numbers: true, prompt: "--", start_year: Time.now.year, end_year: 1900, date_separator: '%s'), '年 ', '月 ')
 .field_with_errors
   + "日"

     # 〜省略〜

これを回避する方法はいくつかあるようですが、今回は以下のように、「config/application.rb」に「config.action_view.field_error_proc = Proc.new { |html_tag, instance| html_tag }」を追記しました。
追記後、サーバーを再起動すると、追記が反映され、Railsによる自動挿入が回避できます。

config/application.rb
   # 〜省略〜

module FleamarketAppTeamA
  class Application < Rails::Application

   # 〜省略〜

    config.action_view.field_error_proc = Proc.new { |html_tag, instance| html_tag }
  end
end


最後に

最後まで読んでいただきありがとうございます。
以上で、ユーザー新規登録についての実装は終わりです。

本記事はカスタムの部分で、大枠の作業フローと、小技的なところで参考にはなるかと思いますので、活用いただければ幸いです。
もっとわかりやすい記事、個々の機能で詳しく記載された記事はたくさんございますので、そこに至るまでのキッカケにもなればとも思っております。

今回私も、以下の記事を主に参考にさせていただきました。
作者の方々には感謝申し上げます。

量が多いため割愛させていただいておりますが、他にも参考にした記事はたくさんありますので、それら記事にも感謝です。
本記事を参考にされる方は、それらの記事も参考にしていただければと思います。

参考記事

・deviseについて
-> rails devise完全入門!結局deviseって何ができるの?
-> 【Rails】deviseの使い方を徹底解説!
-> Deviseでログイン機能をつくる [Ruby on Rails]
-> Deviseの設定手順をまとめてみた。 その1 導入編

・encrypted_password
->Gem Deviseによるパスワードの保存及び保安方法

・add_index
->データベースにindexを張る方法

・正規表現とは
-> https://www.megasoft.co.jp/mifes/seiki/about.html

・正規表現(ライブラリ)
-> https://github.com/kkos/oniguruma/blob/master/doc/RE.ja
-> http://k-takata.o.oo7.jp/mysoft/bregonig.html

・正規表現(確認ツール)
-> https://rubular.com/

・protect_from_forgery with: :exception(CSRF対策)
-> RailsのCSRF保護を詳しく調べてみた(翻訳)

・日本語化
-> https://qiita.com/kusu_tweet/items/b534c808ac1ee0382f05)

・エラー表示
-> ActiveRecordのvalidatesで表示されるエラーメッセージのフォーマットを変更する
-> 【Rails】バリデーションのエラーメッセージを取得・表示・日本語化する方法を完全解説!

・生年月日の選択
-> 【Rails】date_selectタグの使い方メモ
-> Railsのバリデーションエラーで、「field_with_errors」によるレイアウト崩れを防ぐ

辞書

・gem
 便利な機能をひとまとめにしたもの(ライブラリ)

・devise
 ユーザー新規登録/ログインといった認証機能を簡単に実装できるgemのこと

・encrypted_password
 暗号化されたパスワードを保存するカラム

・add_index
 特定のカラムからデータを取得する際に、テーブルの中の特定のカラムのデータを複製し検索が行いやすいようにする

・正規表現
 「検索」や「置換」で指定する文字列をパターン表現する方法で、プログラミング言語やテキストエディタなどで利用できる

・protect_from_forgery with: :exception
 セキュリティ対策。このコードがあると、Railsで生成されるすべてのフォームとAjaxリクエストにセキュリティトークンが自動的に含まれ、セキュリティトークンがマッチしない場合ははじかれる。ユーザー認証が完了したwebアプリのページに悪意のあるコードやリンクを仕込むCSRF(Cross-Site Request Forgery)という攻撃手法から保護出来る。

・before_action
 全てのアクションが実行される前に、この部分が実行される

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【Vuex, Nuxt.js】子コンポーネントのアクションを実行しても状態が反映されない

最近Nuxt.jsを使ってサービスの開発をしてみてます。

フロントエンドのフレームワークの経験がなく慣れておらず、

状態管理でハマったところがあったので備忘録として投稿。

個人的にはてなブログにかいてましたが
技術系はQiitaに書こうと決めたので内容は下記の書き直しとなります。
https://moritomo7315.hatenablog.com/entry/vuex/state_manage/1

ちなみにログイン認証等は今回の記事の本質とは離れてるので割愛してます。

何にハマったか

userのログイン・ログアウトをVuexで

// login
loginStatus = true
// logout
loginStatus = false

のように状態管理しようとしたわけですが、下記のような現象が起きてしまいました。

  • ログアウトする場合:loginStatusがtrue->falseに変化
  • ログインする場合:loginStatusがfalseのまま

ソースコード

store

index.js
import Vuex from 'vuex'
import user from './modules/user'

export default () => new Vuex.Store({
  modules: {
    user
  }
})
user.js
const state = {
  user: null,
  loginStatus: false
}

const getters = {
  user: (state) => state.user,
  isLogin: (state) => state.loginStatus
}

const mutations = {
  setUser(state, { user }) {
    state.user = user
  },
  login(state) {
    state.loginStatus = true
  },
  logout(state) {
    state.loginStatus = false
    state.user = null
  }
}

const actions = {
  fetchUser({ commit }, user) {
    commit('setUser', {user})
  },
  login({ commit }) {
    commit('login')
  },
  logout({ commit }) {
    commit('logout')
  }
}

export default {
  namespaced: true,
  state,
  getters,
  actions,
  mutations
}

header コンポーネント

header.vue
<template>
  <div>
    <v-app-bar
      color="primary"
    >
      <v-toolbar-title>
        <nuxt-link to='/'>
          <img src="~/static/weblogo.png">
        </nuxt-link>
      </v-toolbar-title>
      <v-spacer></v-spacer>
      <v-menu offset-y>
        <template v-slot:activator="{ on }">
          <v-btn
            icon
            color="transparent"
            v-on="on"
          >
            <v-app-bar-nav-icon></v-app-bar-nav-icon>
          </v-btn>
        </template>
        <v-list v-if="loginStatus">
          <v-list-item
            nuxt
            to='#'
          >
            <v-list-item-title>マイページ</v-list-item-title>
          </v-list-item>
          <v-list-item
            @click="logout"
            nuxt
            to='/'
            inactive
          >
            <v-list-item-title>ログアウト</v-list-item-title>
          </v-list-item>
        </v-list>
        <v-list v-else>
          <v-list-item
            nuxt
            to='/login'
          >
            <v-list-item-title>ログイン</v-list-item-title>
          </v-list-item>
          <v-list-item
            nuxt
            to='/signup'
          >
            <v-list-item-title>会員登録</v-list-item-title>
          </v-list-item>
        </v-list>
      </v-menu>
    </v-app-bar>
  </div>
</template>
<script>
import { mapState, mapGetters, mapActions } from 'vuex';

export default {
  name: "Header",
  computed: {
    ...mapState({
      user: state => state.user.user,
      loginStatus: state => state.user.loginStatus
    })
  },
  methods: {
    ...mapActions('user',[
      "logout"
    ])
  }
}
</script>

login page

login.vue
<!-- EmailSigninコンポーネントを呼び出してるだけ。今後Twitterログイン等も入れたいので、コンポーネントに分けている -->
<template>
  <EmailSignin />
</template>

<script>
import EmailSignin from '~/components/emailSignin'
export default {
  components: {
    EmailSignin
  }
}
</script>
emailSignin.vue
<template>
  <div class="userpage">
    <h1>ログイン</h1>
    <div class="userform">
      <v-form>
        <v-text-field
          v-model="email"
          label="E-mail"
          outlined
          required
        ></v-text-field>

        <v-text-field
          v-model="password"
          label="password"
          outlined
          type="password"
          required
        ></v-text-field>
        <v-btn
          color="secondary"
          class="mr-4"
          @click="login"
          x-large
          nuxt
          to="/"
        >
          ログイン
        </v-btn>
        <nuxt-link
          to="#"
        >
          パスワードを忘れた方はこちら...
        </nuxt-link>
      </v-form>
    </div>
  </div>
</template>

<script>
import { mapState, mapGetters, mapActions } from "vuex";

export default {
  name: "EmailSignin",
  data() {
    return {
      email: '',
      password: '',
    }
  },
  computed: {
    ...mapState({
      user: state => state.user.user,
      loginStatus: state => state.user.loginStatus
    })
  },
  methods: {
    ...mapActions('user',[
      "login"
    ]),
    passworLogin () {
      this.login()
    }
  }
}
</script>

何が問題だったか

結論から言うと、

@clickの使い方が原因でした。

ソースコードでいうと、storeの記述に関しては問題なしです。

なぜログアウトはできて、ログインができなかったか

なぜログアウトはできるのに、
ログインはできないといった現象が起きてしまっていたかと言うと、

これは親子コンポーネントとイベントの関係があるみたいです。

僕のソースコードで実装されてるログアウトとログインの違いは

  • headerコンポーネントがコンポーネント内のアクションlogoutを呼びイベント発生
  • loginコンポーネントがemailSigninコンポーネント内のloginを呼びイベント発生

となっております。

どちらも@click="methodNameとしていますが、

ログインだけ動かないのはコンポーネントの親子関係が原因でした。

親コンポーネントに子コンポーネントのアクションイベントを実行させるには、

@click.native="methodName

と指定する必要があるみたいです。

まとめ

コンポーネントの親子関係を意識して、

そのコンポーネントが親か子に応じて

@click@click.nativeを指定するで解決しました。

まだvuexの概念を理解しきっていないので、

説明に使用してる言葉があやしいところもあるかもしれませんが、

無事解決できました。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

TWITTERとyoutubeのビデオをダウンロード

https://www.reiwarss.com/reiwadl

家にいるうちにreiwarss.com/reiwadl
を使ってTWITTERとyoutubeのビデオをダウンロードして学習せよ.
マニュアル:

  1. copy URL .例: youtube.com/watch?v=gn4nRC…
  2. 令和download をクリックする

while fighting with covid-19, try this tool to download the video you like and learn at home .

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

「パスワードは次のメールでお送りします」をやめるためのツールを作った

リポジトリは https://github.com/nabetani/mandihe/

mandihe は、MANual DIffie-HEllman から。

手順

  1. Alice→Bob: 鍵交換支援HTMLを生成するHTMLへのアクセスを提供する。
  2. Alice→Bob: 公開鍵を伝える。
  3. Bob: 鍵交換支援HTMLと Alice からもらった公開鍵を使って、パスワードとダイジェストを作る。
  4. Bob→Alice: ダイジェストとBobの公開鍵を Alice に伝える
  5. Alice: Bobからもらった公開鍵で、パスワードとダイジェストを作る。手元で作られたダイジェストと Bobからもらったダイジェストが一致していることを確認する。
  6. Ailce→Bob: 一致しているからOKだよ、と伝える。

Alice と Bob の間の通信はすべて平文でOK。盗聴されても問題ない。
盗聴+改竄だと困ると思う。
盗聴+改竄 に耐えるようにするには認証局(のようなもの)がないと無理なんじゃないかと思っているんだけど、どうだろう。

(1) の「鍵交換支援HTMLを生成するHTMLへのアクセスを提供」は、平文で HTML を送ってもいいし、サーバーに置いて URL を伝えてもいい。

仕組み

鍵交換をメールなどを通じて行う。

鍵交換の情報の流れは下図の通り:

image.png

「鍵交換支援HTMLを生成するHTML」がある理由

鍵交換支援HTMLは、 crypto.subtle.generateKey で鍵ペアを作る。
HTML を表示するたびに鍵ペアを作るようにすると、

2.Alice→Bob: 公開鍵を伝える。

5.Alice: 手元で作られたダイジェストと Bobからもらったダイジェストが一致していることを確認する。

の間に数日空いたりすると運用上面倒なことになる。
面倒を避けるために鍵ペアを記憶したい。
秘密鍵も記憶するので、暗号化したい。
暗号化には鍵が要る。
では、その鍵はどこに保存するか...という問題がある。

そこで

  • 鍵は、 crypto.getRandomValues で生成。
  • 生成した鍵は「鍵交換支援HTML」内の JavaScript のソースコードに埋め込む。

という作戦にした。
これで、 localStorage であっても安全に秘密鍵を保管することができる。

情報の流れは下図の通り:

image.png

index.html が「鍵交換支援HTMLを生成するHTML」で、 key-exchange-helper.html が「鍵交換支援HTML」である。

  1. 「鍵交換支援HTMLを生成するHTML」内でパスワードを生成
  2. 生成したパスワードを埋め込んだHTMLを「鍵交換支援HTMLを生成するHTML」内で生成
  3. 生成したHTMLを Base64 にして、href に入れる
  4. リンクを右クリック→名前を付けて保存 で、できたての HTML をダウンロード

という流れになる。
パスワードの生成からダウンロードまでの流れに通信が絡まないので傍受できない。

これで、
* localStorage にデータがあればそれを表示
* なければ生成
という処理にすることができる。
これで運用上の面倒がなくなる。

動作するブラウザ

手元で調べたところ

  • 最新の Firefox
  • 最新の Google Chrome
  • 最新の Microsoft Edge(Chromium版)

で動作することがわかった。調べたのは macOS版 と Windows版。

一方。

  • 最新の Safari on macOS
  • 最新の Internet Explorer 11 on Windows

では動作しない事がわかった。残念。
非 Chromium の Edge は手元にないので試していない。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

bootstrap-selectの選択済み項目をJavaScriptで変更する際の注意点

bootstrap-selectプラグインを使ってドロップダウンリストを作成した場合は、JavaScriptで $("ドロップダウンリスト").val("変更したい値") で値を変更しただけでは表示が変更されない。
bootstrap-selectプラグインを使う場合は値のセットとは別に表示の変更を書く必要がある。

標準のドロップダウンリストは以下のようにすれば selected が変更され、表示も変更される。

html
<select name="vegetable" class="selectpicker">
   <option value="carrot">にんじん</option>
   <option value="onion" selected>たまねぎ</option>
   <option value="potato">じゃがいも</option>
   <option value="broccoli">ブロッコリー</option>
</select>
javascript
$("select[name=vegetable]").val("potato");
$(".selectpicker").selectpicker("render");

refresh でも表示の変更は可能だが、こちらはoption要素の追加・削除など、もっと高度な変更に使用するもののようだ。 ※参考サイト

$(".selectpicker").selectpicker("refresh");
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

jxaを使ってXcodeのSimulate Locationをキー入力で書き換えるアプリを作った

以前作ったアプリのデバッグの際にSimulate Locationにはお世話になったのですが、毎回行きたい場所のgpxファイルを追加する必要があり、かなり面倒くさかったです。以下の記事で紹介されているAppleScriptは改良する気が起きなかったのでその時は手動でぽちぽちしてました。

iPhoneの実機で位置情報をシミュレーションする方法 - Qiita

JavaScriptで書ける

知らないうちにMacがシステム標準でJavaScriptで操作できるようになってた (JXA) - Qiita

ずっとMac使ってたのですが、知りませんでした:scream_cat:
JavaScirptで書けるということでちょっと触ってみたところ、結構おもしろい。

作ったもの

output.gif

処理の流れ

  1. 作ったアプレット(.app)起動
  2. gpxファイルをアプレット(.app)にドラッグ&ドロップ
  3. 上下左右の選択ボックスが現れるので選ぶ
  4. 選択された方向によりgpxファイルを上書き
  5. XcodeのSimulate Locationにあるgpxファイル名をクリック

以降、3〜5をループ。

コード

コード量は100行程ですが、雑に書いたので主要な箇所だけ。

xxx.js
// ドロップされた時に実行されるハンドラ
const extensionsToProcess = ["gpx"];
const typeIdentifiersToProcess = [];
function openDocuments(droppedItems) {
    for (const item of droppedItems) {
        const alias = systemEvents.aliases.byName(item.toString());
        const extension = alias.nameExtension();
        const fileType = alias.fileType();
        const typeIdentifier = alias.typeIdentifier();
        if (extensionsToProcess.includes(extension) || typeIdentifiersToProcess.includes(typeIdentifier)) {
              const path = Path(item.toString().slice(1));
              changeGpx(path);
        }
    }
}
xxx.js
// gpxファイル読み込み
const finderApp = Application.currentApplication();
finderApp.includeStandardAdditions = true;
const readFile = finderApp.openForAccess(path);
const textGpx = finderApp.read(readFile, {as:"text"})
finderApp.closeAccess(readFile);
xxx.js
// gpxファイル書き込み
const gpxString = `<?xml version="1.0" encoding="utf-8"?>
    <gpx version="1.1">
    <wpt lat="${lat}" lon="${lon}" />
</gpx>`
const writeFile = finderApp.openForAccess(path, {writePermission:true});
finderApp.setEof(writeFile, {to:0})
finderApp.write(gpxString, {to:writeFile, as:"text"})
finderApp.closeAccess(writeFile)
xxx.js
// Xcodeの Debug > Simulate > xxxをクリック
const xcodeApp = Application("System Events").applicationProcesses.byName("Xcode");
const target = xcodeApp.menuBars[0]
.menuBarItems["Debug"].menus["Debug"]
.menuItems["Simulate location"].menus["Simulate location"]
.menuItems[fileName];
target.click();
xxx.js
// chooseFromListでユーザーからの入力待ち
while(true) {
    const selectedItem = systemEvents.chooseFromList(DIRECTIONS, {
        withPrompt: "Please select the direction of travel :",
        defaultItems: [selectedDirection]
    })
    // Cancelの場合は終了
    if (!selectedItem) {
        break;
    }
    selectedDirection = selectedItem.toString();

    switch (selectedDirection) {
        ...
    }
}

jxaのよかったところ

  • JavaScriptで書ける!
  • 簡単にGUIアプリが作れる!
  • 環境構築のためのアプリ、外部のライブラリのインストールが不要!

ってことでプログラムやったことない人でも気軽に触れるのでおすすめ!(Linux、Windows、その他のユーザーには申し訳)

参考

Mac Automation Scripting Guide: About Mac Scripting

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

マルチブラウザ対策について

マルチブラウザとは

アプリケーションが様々なブラウザ上でも同じ動作をすること。
クロスブラウザともほぼ同義であり、マルチブラウザはアプリケーションの製作者が推奨するブラウザで動作することを保証しクロスブラウザは全てのブラウザで動作することを保証することを意味する。

マルチブラウザ対策の5つの方法

 1. cssハック

cssハックとは
ブラウザごとに適応させるcssを変えること

css
/* IE11のみ適応 */
@media all and (-ms-high-contrast: none) {
  *::-ms-backdrop, .selector {
    /* 適用したいスタイル */
  }
}

/* FireFoxのみ適用 */
@-moz-document url-prefix() {
    /* 適用したいスタイル */
}
/* Chrome、Safari、Operaのみ適用 */
@media screen and (-webkit-min-device-pixel-ratio:0) {
    /* 適用したいスタイル(Chrome、Safari、Operaのみ適用) */
}

 2. リセットcssの使用

リセットcssとは

ブラウザでは、デフォルトの余白やフォントの大きさを定義しているため、各ブラウザによってデザインの表示が変わってしまうことがある。
この差異を無くすためにデフォルトで適応されているcssをリセットするためのもの

リセットCSSの読み込み方は、下記の記述をhead内に記述する

html
<!DOCTYPE html>
<html lang="jp">
<head>
  <meta charset="UTF-8">
  <link rel="stylesheet" href="パス/reset.css">
  <title>Document</title>
</head>

 3. cssの記述法

padding, margin, borderなど要素ごとのレンダリングは、全てのブラウザで異なる。
なのでcssの記述に工夫が必要

css
/* 横幅が100pxもしくは150pxとブラウザによって表示が変わってしまう */
div{
  width:100px;
  padding-left:50px;
}

/* widthとpaddingを分けて記述すればどのブラウザでも同じ幅で表示される */
div{
  width:100px;
}
div p{
  padding-left:50px;
}

 4. jQueryの使用

javascriptでは、ブラウザ毎に記述することを意識しなければならないが、jQueryはクロスブラウザに対応しているのでブラウザの違いを特に意識する必要はない

 5. ブラウザ対応状況をチェック

HTML5、CSS3はブラウザによっては使えない場合があるので、プロパティーをブラウザ対応状況を簡単にチェックできるサービスCan I useを使う

スクリーンショット 2020-01-31 0.40.24.png

使い方は 「Can I use ______ ?」の部分に調べたい要素を入力するだけでどのブラウザで対応しているのかを調べることができる。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Node.jsでお天気を取得してみよう

はじめに

OpenWeatherMap APIからお天気情報を取得しようという試みです。
色々な方が、さまざまな言語で同様の記事を上げています。
私は、勉強真っ最中のNode.jsでやってみようと思いました。
(Node.jsの導入はこちら)

環境

wslの環境です。

Editor: VSCode
Shell : bash version 4.4.20
Ubuntu: 18.04.4 LTS
node  : v10.14.2

1.APIの取得

OpenWeatherMapの公式サイトで無料アカウントを作成後、
表示されるAPIキーを控えておいてください。
APIキー取得後は少し時間をおいてか試したほうがいいと思います。
公式もそういってますし。

2.プロジェクトを作成

1.任意の位置(緯度経度)のお天気情報を取得

とりあえず福岡市にしてみました。

app.js
'use strict';

const http = require('http');
const MY_WEATHER_APIKEY = {YOUR_API_KEY};
const LAT = 33.60639;  //緯度
const LON = 130.41806;  //経度
const req = 'http://api.openweathermap.org/data/2.5/weather?lat='+LAT+'&lon='+LON+'&appid='+ MY_WEATHER_APIKEY;

http.get(req, res => {
  var body ='';
  res.setEncoding('utf8');
  res.on('data', (chunk) => {
    body += chunk;
  });
  res.on('end', () => {
    res = JSON.parse(body);
    console.log(res);
  });
})
  .on('error', e => {
    console.error(e.message);
});

{YOUR_API_KEY}に控えておいたAPIキーを入れてください。

実行結果

$ node scripts/app.js 
{ coord: { lon: 130.42, lat: 33.61 },
  weather:
   [ { id: 803,
       main: 'Clouds',
       description: 'broken clouds',
       icon: '04n' } ],
  base: 'stations',
  main:
   { temp: 286.85,
     feels_like: 284.37,
     temp_min: 285.93,
     temp_max: 287.15,
     pressure: 1018,
     humidity: 58 },
  visibility: 10000,
  wind: { speed: 2.1, deg: 300 },
  clouds: { all: 75 },
  dt: 1587901760,
  sys:
   { type: 1,
     id: 7998,
     country: 'JP',
     sunrise: 1587846896,
     sunset: 1587895019 },
  timezone: 32400,
  id: 1863967,
  name: 'Fukuoka',
  cod: 200 }

この結果をいろいろ触って特定の情報を抜き出せます。

weather:
[ { id: 803,
main: 'Clouds',
description: 'broken clouds',
icon: '04n' } ]

が欲しければ、console.log(res.weather);

main: 'Clouds'

が欲しければ、console.log(res.weather[0].main);
という風にすればいいですね。
おぉ、いま福岡の方は曇りなんですね。

2.モジュール化

うまくいったので、モジュール化しました。
のちのちモジュール化しておいたほうが使いまわしやすいと思います。

app.js
'use strict';
const weather = require('./weatherFunc');
const MY_WEATHER_APIKEY = {YOUR_API_KEY};
weather.clweather(MY_WEATHER_APIKEY);
weatherFunc.js
'use strict';
const http = require('http');

function clweather(api){
  const LAT = 33.60639;  //緯度
  const LON = 130.41806;  //経度
  const req = 'http://api.openweathermap.org/data/2.5/weather?lat='+LAT+'&lon='+LON+'&appid='+ api;
  http.get(req, res => {
    let body ='';
    res.setEncoding('utf8');
    res.on('data', (chunk) => {
      body = body.concat(chunk);
    });
    res.on('end', () => {
      res = JSON.parse(body);
      console.log(res);
    });
  })
    .on('error', e => {
      console.error(e.message);
  });
}

module.exports = {
  clweather
}

さいごに

今後の展望としては、現在地の自動取得とか取り入れていけば、
経度、緯度指定にしていることが活きてきて、
もう少し実用的になると思います。

拙い文章でしたしょうが、お付き合いありがとうございました。

さよなら:wave:

関連記事

参考

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

removeclassやaddclassを使用する時に気をつけること

removeclassやaddclassの引数としてクラス名を指定するが、.を入れていたが、それだとは反応しないので、.を抜いて記述する。
というのも、addclassやremoveclassは元々クラス名を前提に引数を指定するものなので、.は必要なかった。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

スワイプをJavaScriptで書いてみた

Twitterのサイドバーのような、スワイプ処理をJavascriptで書いてみました !

コードはこんな感じです.
すべてのコードはこちら

main.js
 function selector(s){
      return document.querySelector(s)
 }

      const t = selector('.flick_space');  // .flick_spaceはタッチ可能範囲のクラス名
      var startX;        // タッチ開始 x座標
      var moveX;        // スワイプ中の x座標
      var flag = 0 ;    // フラグ
      var nav_w =selector('nav').clientWidth ; //サイドバー幅

      // タッチ開始時: xy座標を取得
      t.addEventListener("touchstart", function(e) {
          e.preventDefault();
          startX = e.touches[0].pageX;

      });

          function limit(){
          if(moveX -startX <= nav_w){return -nav_w + (moveX - startX);
            }else{ return 0 }
          }

          function move(){
          if(moveX -startX > 0){return 0 ;
            }else{ return (moveX - startX) }
          }

          function calc(){
           if( flag == 10 ){
              var $obj1 = {
                  func: move(),
                  flag: 0
              }
              return $obj1 ;  
           } else if( flag == 0 ){
             var $obj1 = {
                 func: limit(),
                 flag: 10
             }
             return $obj1 ;  
           }    
         }

      // スワイプ中: xy座標を取得
      t.addEventListener("touchmove", function(event) {
         event.preventDefault();
         moveX = event.changedTouches[0].pageX;
         var $obj2 = calc();

           document.getElementById("nav").style.transition = "margin-left 0ms" ; 
           document.getElementById("nav").style.marginLeft =$obj2.func + 'px' ;//現在の幅(px)

          // console.log($obj2.flag ); 確認用
      });


      // タッチ終了時: スワイプした距離から左右どちらにスワイプしたかを判定する/距離が短い場合もとにもどる
      t.addEventListener("touchend", function(event) {event.preventDefault();
          var nav_w = selector('nav').clientWidth;
          var distance = (moveX - startX );

          if(distance > 40){
              flag = 10; //console.log(flag);
              selector('nav').style.transition = "margin-left  610ms ";  
              document.getElementById("nav").style.marginLeft = 0 + 'px';

          }else{ flag = 0; //console.log(flag);
              selector('nav').style.transition = "margin-left  610ms ";  
              document.getElementById("nav").style.marginLeft = - nav_w + 'px';
          }
      });

ポイント

  • スライドの部分は Margin-Left を使って移動させた  (サイドバーが完全に表示されている状態がmargin-left = 0)
  • flag を付与することによって、サイドバーをスワイプしてコントロールする関数(2つある)を適切に使い分けることができる (ここでは 010)

.style.transition はよく見かけていたのですが、.style.marginLeft というものが使えると初めて知りました ! 確かにcssプロパティなんだからほかも使えるのは当然だなと笑 (参考までに)

誤字・脱字、コードの誤りなどありましたら、コメントお待ちしております !

ここまで読んでくださってありがとうございました.

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Re:ゼロから始めるweb開発 (GAS使用) Part0

タイトル.png
リゼロ ロゴジェネレーターさんのサイトで作成.

はじめに

この記事はGoogle Apps Scriptを用いて,簡単なウェブアプリケーションを開発していく記事となります.
Part0のこの記事では,Google Apps Scriptを使用した理由と,導入についてまとめていけたらと思います.
参考サイトは一番最後にまとめております.

Google Apps Scriptとは

From Wikipedia

Apps Script is a scripting platform developed by Google for light-weight application development in the G Suite platform. Google Apps Script was initially developed by Mike Harm as a side project whilst working as a developer on Google Sheets. Google Apps Script was first publicly announced in May 2009 when a beta testing program was announced by Jonathan Rochelle, then Product Manager, Google Docs. In August 2009 Google Apps Script was subsequently made available to all Google Apps Premier and Education Edition customers. It is based on JavaScript 1.6, but also includes some portions of 1.7 and 1.8 and a subset of the ECMAScript 5 API. Apps Script projects run server-side on Google's infrastructure. According to Google, Apps Script "provides easy ways to automate tasks across Google products and third party services." Apps Script is also the tool that powers the add-ons for Google Docs, Sheets and Slides.

一応wikipediaに記載されているもの記載しましたが,自分自身もあまりweb関係に詳しくないので,わかりにくいなと感じました.
@ochilab さんの「Google Apps Scriptでお手軽にウェブサーバーアプリ開発をしてみよう」の記事に書いてあったものがすごくわかりやすかったので引用させていただきます.

Googleが提供しているG Suite(Google Document, SpreadSheet, Slide, Forms, Drive)などで動作させることができるスクリプト実行環境です。GASという略称がよく使われています。ExcelでいうVBAみたいな位置づけになるといえばわかりやすいでしょう。実際、Google SpreadSheetと連携させることが多かったりします。さらに本日のお題で挙げているようにウェブアプリケーションを開発することもできます。言語はJavaScriptです。

「Google Apps Script」の頭文字をとってGASと略されることが多いため,これ以降はGASと省略した形で書いていきます.

GASのメリット

【Google Apps Script入門】GASでできることや活用方法まで紹介!や,先ほど挙げた「Google Apps Scriptでお手軽にウェブサーバーアプリ開発をしてみよう」の記事に書いてあることを中心にまとめていきます.

開発環境の整備が不要

プログラミングをする場合,多くの方が開発環境を作る段階で躓きます.
自分が在学する大学では,C++を最初に習いますが,やはり環境設定でかなり多くの学生が躓きます.
その点,GASはサーバ上に実行環境があるため,GoogleアカウントとPCがあれば利用することができるため始めやすいと感じています.

Googleサービスや外部サービスとの提携が可能

GASはGoogleが提供しているさまざまなサービスと連携が容易にできます.
特に,GoogleスプレッドシートやGoogleカレンダーとの相性は抜群だと感じています.
また,外部のサービスとも連携が可能であり,yahooが提供している形態素解析と連携し利用したり,slackなどと連携し,botなどを開発することができるので,ゆくゆくは発展的なことを実装することもできると思いました.

様々な開発が可能

本記事で扱う予定であるWebアプリケーション開発ができるだけでなく,Webサイトからの情報収集をするプログラムや,対話システムもどき,botなど様々なものを作成することができます.
特に,Webアプリケーション開発においては,サーバ契約することなくサーバレスでWebアプリが作れるのは,お金がかからず練習として作るには持ってこいだと思います.
さらにGASはトリガーという仕組みがあり,定期的に指定した時間にプログラムを実行することができるため,Googleスプレッドシートをデータベースのように扱い,スクレイピングした情報を蓄積することや,slackと連携して予定を教えてくれるbotなどを作成することができます.
GASはJavaScriptで書くことができ,一つの言語でこれだけのことができるのは,かなり魅力的だと思います.
JavaScriptは,プログラミング言語の中でも,学びやすい部類なので,大学に入って心機一転,web開発などを学びたいと思う人にはベストな選択枝なのではと思い,GASを用いてゼロから記事を書くことにしました.

GASのデメリット

無料サービスであるため,制約が多少ありますが,初めてweb開発をするのであれば,なんら問題はないです.
後からお金を要求されるとか,そういう怖いデメリットはまったくないので安心して使ってもらえたらと思います.

GASを使ってみる(Webアプリの公開)

いよいよ本題です.
とりあえず,何を始めたらいいかわからない人向けに,手順を説明できたらと思います.
Googleスプレッドシートからスクリプトエディタを開く方法が有名ですが,今回はとにかくシンプルにやる方法を記載していきたいと思います.
Google Apps ScriptでWebアプリケーションを作る最初の一歩をあたりを参考にしています.

1. スクリプトファイルを開く

googleドライブをブラウザで開き,googleドライブの「新規」→「その他」→「Google Apps Script」を選択します.
image.png
そうすると無題のプロジェクトと書かれたスクリプトファイルが開かれると思います.
これで大丈夫です.
image.png
ファイルの名前もせっかくなので変更しましょう.
他のGoogleのドキュメントやスライド同様,直接「無題のプロジェクト」をクリックすれば変更を加えることができます.
適当に名前を変えましょう.自分は「test」にしました.
image.png

2. htmlファイルの作成

次にページを表示するためにHTMLファイルを作成する必要がありますが難しくありません.
基本的にGASでWebアプリを作成する場合は,処理を行うGASのスクリプトファイルとブラウザにどのように表示させるか決めるHTMLファイルがセットで必要になります.
HTMLファイルの作成は「ファイル」→「New」→「HTMLファイル」を選択します.
image.png
選択すると以下のような画面になると思います.
image.png
ファイル名は何でもいいですが,「index」にしました.
とりあえず何か表示させたいので,図の矢印部分である7行目に,

    <h1>テスト</h1>

と書いておいて保存しておいてください.
保存は図の赤丸のとこを押せば保存できます.

3. スクリプトファイルにプログラムを書く

「コード.gs」のタグを押して,スクリプトファイルの編集に戻ります.
最初に自動で記載されているmyFunctionは使わないので消してもらい,以下のコードをコピー&ペーストしてください.

function doGet() {
  // ここでindex.htmlを受け取れるようにする.拡張子.htmlは省略するとのこと.
  return HtmlService.createTemplateFromFile("index").evaluate();
}

コピー&ペーストしたら,保存をしてください.
下の画像のようになっていれば大丈夫です.
image.png

「コード.gs」のタグのコードの横に赤いがある場合は保存ができていないので,もう一度保存押してみてください.
このコードが何をしているのかの詳しい説明は,本記事の趣旨とはそれるので省きますが,参考としている「Google Apps ScriptでWebアプリケーションを作る最初の一歩」の「
doGet関数を作成する*」で細かく説明があるので,余裕がある方は読んでみてください.

4. 作成したWebアプリの公開

アプリと呼べるような大層なものは作っていませんが,公開してみましょう.
Webアプリとして公開するには,「公開」→「ウェブアプリケーションとして導入…」を選択します.
image.png
そのあと以下のウィンドウが表示されると思うので順に説明します.
image.png
最初の赤枠はProject versionについてですが,Newにしてください.基本的に常にNewで大丈夫です.
その下の赤枠は何をしたのかコメントを記入しておいてください.(後々あると助かることが多いですが空白でも可です)
Execute the app as:のところは,「me」か「自分」になっていれば大丈夫です.(メアドあったので塗りつぶしてます)
Who has access to the app:は誰がそのページを見ることができるかです.
「自分だけ」,「全ユーザー」,「匿名を含む全ユーザー」から選べます.
開発段階なら「自分だけ」でいいですが,見られて困る情報もページには記載してないので,「匿名を含む全ユーザー」を選択してます.
最後に,Deployを押せば終わりです.
お疲れさまでした.

ページの確認

最後に,作成したWebアプリのページを見てみましょう.
Deployを押した後に,以下の画像のようなウィンドウが出たと思います.
image.png
このURLが開発したWebアプリのページとなります.
試しに,URLをコピーしてブラウザで開いてみてください.
image.png
今回は,index.htmlに「テスト」と表示することしか記述してないので,これで終わりですが,htmlファイルとスクリプトファイルにやりたいことを色々書いたり,Googleスプレッドシートと連携させたりすることで,様々なことができるようになるので,次の記事を楽しみにして待ってもらえたらと思います!

最後に

次の記事で,どのような機能を追加するかなどはまったく決めていません.
記事を書いた自分は,GASとGoogleスプレッドシートとSlackを連携させて,勉強したものを記録したり,一週間前に勉強した内容などを毎朝復習できるように通知したりするシステムを家庭教師の仕事の一環で作成したことがあり,ある程度GASを使っていろいろなことができる気がしています.
なので,コメントでどういうものを作って紹介してほしいかなど教えてもらえたら,時間が許す範囲で実装して紹介してみたいと思うので,気軽にコメントください!
記事書きなれておらず,読みにくかったり至らない点も多かったと思いますが,最後まで読んでいただきありがとうございました.
少しでも「参考になった」,「続きが読みたい」と思ってくれた方は,いいねしてもらえると嬉しいです.(モチベになるので)

参考サイト一覧

Wikipedia
Google Apps Scriptでお手軽にウェブサーバーアプリ開発をしてみよう
【Google Apps Script入門】GASでできることや活用方法まで紹介!
Google Apps ScriptでWebアプリケーションを作る最初の一歩

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

P5.js 日本語リファレンス(bezierPoint)

このページでは「P5.js 日本語リファレンス」 の bezierPoint関数を説明します。

bezierPoint()

説明文

ポイント a、b、c、d の位置 t の bezier 値を算出します。パラメータ a と d はカーブの最初と最後のポイントで、b と c は制御点です。パラメータ t は0と1の間で変化します。これは x 座標、y 座標それぞれで実行して t でのベジエ曲線の位置を取得できます。

構文

bezierPoint(a, b, c, d, t)

パラメタ

  • a

    Number:曲線上の最初の点の座標

  • b

    Number:最初の制御点の座標

  • c

    Number:2番目の制御点の座標

  • d

    Number:曲線上の2番目の点の座標

  • t

    Number:0と1の間の値

戻り値

Number:位置 t での bezier の値

例1

function draw(){
  noFill();
  let x1 = 85,
      x2 = 10,
      x3 = 90,
      x4 = 15;

  let y1 = 20,
      y2 = 10,
      y3 = 90,
      y4 = 80;

  bezier(x1, y1, x2, y2, x3, y3, x4, y4);
  fill(255);
  let steps = 5;

  for(let i = 0; i <= steps; i++){
    let t = i / steps;
    let x = bezierPoint(x1, x2, x3, x4, t); // bezier 曲線上の x 座標を算出
    let y = bezierPoint(y1, y2, y3, y4, t); // bezier 曲線上の y 座標を算出
    ellipse (x, y, 5, 5); // 算出したxy座標上に円を描画
  }
}

実行結果

bezierPoint.png

著作権

p5.js was created by Lauren McCarthy and is developed by a community of collaborators, with support from the Processing Foundation and NYU ITP. Identity and graphic design by Jerel Johnson.

ライセンス

Creative Commons(CC BY-NC-SA 4.0) に従います。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【jQuery】全選択したチェックボックスの値を配列で取得

フォーム画面などでよく見かける、次のようなUIサンプルの作り方。(最後にサンプルもあります)

  • チェックボックスの全選択・全解除
  • 全選択をチェック後、各選択肢のチェックを外す => 全選択のチェックが外れる。
  • 各選択肢のチェックボックスを全てチェックする => 全選択がチェックされる。
  • ボタンを押したとき、チェックされているチェックボックスの値を配列で取得する。

HTML

html
<!-- 全選択 -->
<label><input type="checkbox" id="check_all" name="check_all">すべて</label>

<!-- 選択肢 -->
<div id="items">
  <label><input type="checkbox" name="fruits" value="apple" class="item">りんご</label>
  <label><input type="checkbox" name="fruits" value="banana" class="item">バナナ</label>
  <label><input type="checkbox" name="fruits" value="grapes" class="item">ぶどう</label>
  <label><input type="checkbox" name="fruits" value="orange" class="item">オレンジ</label>
  <label><input type="checkbox" name="fruits" value="strawberry" class="item">いちご</label>
</div>

<!-- ボタン -->
<input type="button" value="チェックボックスの値を配列で取得" id="get_values">

input要素をlabel要素で括っておけば、チェックボックスとテキスト部分のどちらをクリックしても、チェックが入るので使い勝手が良くなります。

チェックボックスの全選択・解除

1. 「選択肢」のチェック状態を切替える

JavaScript
$('#check_all').on('change', function() {
  // 「選択肢」のチェック状態を切替える
  $('.item').prop('checked', $(this).is(':checked'));
});

処理はシンプルで、「全選択」と「各選択肢」の状態を同じにしているだけです。

  • 「全選択」がチェックされている :「選択肢」もすべてチェックする。
  • 「全選択」のチェックが外れている:「各選択肢」もすべてチェックを外す。

$(this).is(':checked')で、「全選択」のチェック状態を取得しています。
なお、この箇所は$(this).prop('checked')とかthis.checkedでもOKです。

2. 「全選択」のチェック状態を切替える

JavaScript
$('.item').on('change', function() {
  // 「全選択」のチェック状態を切替える
  if ($('#items :checked').length == $('#items :input').length){
    $('#check_all').prop('checked', true);
  }else{
    $('#check_all').prop('checked', false);
  }
});

各選択肢をチェックしたとき、選択肢のチェックボックス数と、チェック状態の数を比較します。

  • 数が同数    :「すべて」をチェック状態にします。 => .prop('checked', true)
  • 数が同数ではない:「すべて」のチェックを外します。  => .prop('checked', false)

チェックした値を配列で取得

.each() を使用

JavaScript
$('#get_values').on('click', function() {

  var vals = []; // 配列を定義
  $('input[name="fruits"]:checked').each(function() {
      vals.push( $(this).val() ); // 配列に値を追加
  });

  console.log(vals);
});

チェック済みのinput要素を.each()対象にするので、
input[name="name属性名"]:checkedのように、セレクタに:checkedを付けます。

チェック済みの値を格納する配列valsを定義しておき、.push()で追加しましょう。

実行結果(ボタンをクリック)
// 「りんご」と「オレンジ」のみチェック
["apple", "orange"]

ボタンを押せば、チェック済みの値が配列で取得できます。

.map() を使用

JavaScript
$('#get_values').on('click', function(){

  var vals = $('input[name="fruits"]:checked').map(function() {
    return $(this).val();
  }).get();

  console.log(vals);
});

.map()を使用しても、実行結果は.each()と同じです。

完成(サンプル)

最後に完成形の全体コードを載せておきます。(.map()版)

<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="utf-8">
<title>【jQuery】全選択したチェックボックスの値を配列で取得</title>
<script src="https://code.jquery.com/jquery-3.4.1.min.js"></script>
<script>
$(function() {
  // チェックボックスの全選択・解除
  $('#check_all').on('change', function() {
    // 「選択肢」のチェック状態を切替える
    $('.item').prop('checked', $(this).is(':checked'));
  });

  $('.item').on('change', function() {
    // 「全選択」のチェック状態を切替える
    if ($('#items :checked').length == $('#items :input').length){
      $('#check_all').prop('checked', true);
    }else{
      $('#check_all').prop('checked', false);
    }
  });


  // チェックした値を配列で取得
  $('#get_values').on('click', function(){

    var vals = $('input[name="fruits"]:checked').map(function() {
      return $(this).val();
    }).get();

    console.log(vals);
  });
});
</script>
</head>
<body>
  <!-- 全選択 -->
  <label><input type="checkbox" id="check_all" name="check_all">すべて</label>

  <!-- 選択肢 -->
  <div id="items">
    <label><input type="checkbox" name="fruits" value="apple" class="item">りんご</label>
    <label><input type="checkbox" name="fruits" value="banana" class="item">バナナ</label>
    <label><input type="checkbox" name="fruits" value="grapes" class="item">ぶどう</label>
    <label><input type="checkbox" name="fruits" value="orange" class="item">オレンジ</label>
    <label><input type="checkbox" name="fruits" value="strawberry" class="item">いちご</label>
  </div>

  <!-- ボタン -->
  <input type="button" value="チェックボックスの値を配列で取得" id="get_values">
</body>
</html>
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

JavaScript: 選択したチェックボックスの値を配列で取得

フォーム画面などでよく見かける、次のようなUIサンプルの作り方。(最後にサンプルもあります)

  • チェックボックスの全選択・全解除
  • 全選択をチェック後、各選択肢のチェックを外す => 全選択のチェックが外れる。
  • 各選択肢のチェックボックスを全てチェックする => 全選択がチェックされる。
  • ボタンを押したとき、チェックされているチェックボックスの値を配列で取得する。

HTML

html
<!-- 全選択 -->
<label><input type="checkbox" id="check_all" name="check_all">すべて</label>

<!-- 選択肢 -->
<div id="items">
  <label><input type="checkbox" name="fruits" value="apple" class="item">りんご</label>
  <label><input type="checkbox" name="fruits" value="banana" class="item">バナナ</label>
  <label><input type="checkbox" name="fruits" value="grapes" class="item">ぶどう</label>
  <label><input type="checkbox" name="fruits" value="orange" class="item">オレンジ</label>
  <label><input type="checkbox" name="fruits" value="strawberry" class="item">いちご</label>
</div>

<!-- ボタン -->
<input type="button" value="チェックボックスの値を配列で取得" id="get_values">

input要素をlabel要素で括っておけば、チェックボックスとテキスト部分のどちらをクリックしても、チェックが入るので使い勝手が良くなります。

チェックボックスの全選択・解除

1. 「選択肢」のチェック状態を切替える

JavaScript
$('#check_all').on('change', function() {
  // 「選択肢」のチェック状態を切替える
  $('.item').prop('checked', $(this).is(':checked'));
});

処理はシンプルで、「全選択」と「各選択肢」の状態を同じにしているだけです。

  • 「全選択」がチェックされている :「選択肢」もすべてチェックする。
  • 「全選択」のチェックが外れている:「各選択肢」もすべてチェックを外す。

$(this).is(':checked')で、「全選択」のチェック状態を取得しています。
なお、この箇所は$(this).prop('checked')とかthis.checkedでもOKです。

2. 「全選択」のチェック状態を切替える

JavaScript
$('.item').on('change', function() {
  // 「全選択」のチェック状態を切替える
  if ($('#items :checked').length == $('#items :input').length){
    $('#check_all').prop('checked', true);
  }else{
    $('#check_all').prop('checked', false);
  }
});

各選択肢をチェックしたとき、選択肢のチェックボックス数と、チェック状態の数を比較します。

  • 数が同数    :「すべて」をチェック状態にします。 => .prop('checked', true)
  • 数が同数ではない:「すべて」のチェックを外します。  => .prop('checked', false)

チェックした値を配列で取得

.each() を使用

JavaScript
$('#get_values').on('click', function() {

  var vals = []; // 配列を定義
  $('input[name="fruits"]:checked').each(function() {
      vals.push( $(this).val() ); // 配列に値を追加
  });

  console.log(vals);
});

チェック済みのinput要素を.each()対象にするので、
input[name="name属性名"]:checkedのように、セレクタに:checkedを付けます。

チェック済みの値を格納する配列valsを定義しておき、.push()で追加しましょう。

実行結果(ボタンをクリック)
// 「りんご」と「オレンジ」のみチェック
["apple", "orange"]

ボタンを押せば、チェック済みの値が配列で取得できます。

.map() を使用

JavaScript
$('#get_values').on('click', function(){

  var vals = $('input[name="fruits"]:checked').map(function() {
    return $(this).val();
  }).get();

  console.log(vals);
});

.map()を使用しても、実行結果は.each()と同じです。

完成(サンプル)

最後に完成形の全体コードを載せておきます。(.map()版)

<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="utf-8">
<title>全選択したチェックボックスの値を配列で取得</title>
<script src="https://code.jquery.com/jquery-3.4.1.min.js"></script>
<script>
$(function() {
  // チェックボックスの全選択・解除
  $('#check_all').on('change', function() {
    // 「選択肢」のチェック状態を切替える
    $('.item').prop('checked', $(this).is(':checked'));
  });

  $('.item').on('change', function() {
    // 「全選択」のチェック状態を切替える
    if ($('#items :checked').length == $('#items :input').length){
      $('#check_all').prop('checked', true);
    }else{
      $('#check_all').prop('checked', false);
    }
  });


  // チェックした値を配列で取得
  $('#get_values').on('click', function(){

    var vals = $('input[name="fruits"]:checked').map(function() {
      return $(this).val();
    }).get();

    console.log(vals);
  });
});
</script>
</head>
<body>
  <!-- 全選択 -->
  <label><input type="checkbox" id="check_all" name="check_all">すべて</label>

  <!-- 選択肢 -->
  <div id="items">
    <label><input type="checkbox" name="fruits" value="apple" class="item">りんご</label>
    <label><input type="checkbox" name="fruits" value="banana" class="item">バナナ</label>
    <label><input type="checkbox" name="fruits" value="grapes" class="item">ぶどう</label>
    <label><input type="checkbox" name="fruits" value="orange" class="item">オレンジ</label>
    <label><input type="checkbox" name="fruits" value="strawberry" class="item">いちご</label>
  </div>

  <!-- ボタン -->
  <input type="button" value="チェックボックスの値を配列で取得" id="get_values">
</body>
</html>
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

JavaScript: 全選択したチェックボックスの値を配列で取得するサンプル

フォーム画面などでよく見かける、次のようなUIサンプルの作り方。(最後にサンプルもあります)

checkbox_array.gif

  • チェックボックスの全選択・全解除
  • 全選択をチェック後、各選択肢のチェックを外す => 全選択のチェックが外れる。
  • 各選択肢のチェックボックスを全てチェックする => 全選択がチェックされる。
  • ボタンを押したとき、チェックされているチェックボックスの値を配列で取得する。

HTML

html
<!-- 全選択 -->
<label><input type="checkbox" id="check_all" name="check_all">すべて</label>

<!-- 選択肢 -->
<div id="items">
  <label><input type="checkbox" name="fruits" value="apple" class="item">りんご</label>
  <label><input type="checkbox" name="fruits" value="banana" class="item">バナナ</label>
  <label><input type="checkbox" name="fruits" value="grapes" class="item">ぶどう</label>
  <label><input type="checkbox" name="fruits" value="orange" class="item">オレンジ</label>
  <label><input type="checkbox" name="fruits" value="strawberry" class="item">いちご</label>
</div>

<!-- ボタン -->
<input type="button" value="チェックボックスの値を配列で取得" id="get_values">

input要素をlabel要素で括っておけば、チェックボックスとテキスト部分のどちらをクリックしても、チェックが入るので使い勝手が良くなります。

チェックボックスの全選択・解除

1. 「選択肢」のチェック状態を切替える

JavaScript
$('#check_all').on('change', function() {
  // 「選択肢」のチェック状態を切替える
  $('.item').prop('checked', $(this).is(':checked'));
});

処理はシンプルで、「全選択」と「各選択肢」の状態を同じにしているだけです。

  • 「全選択」がチェックされている :「選択肢」もすべてチェックする。
  • 「全選択」のチェックが外れている:「各選択肢」もすべてチェックを外す。

$(this).is(':checked')で、「全選択」のチェック状態を取得しています。
なお、この箇所は$(this).prop('checked')とかthis.checkedでもOKです。

2. 「全選択」のチェック状態を切替える

JavaScript
$('.item').on('change', function() {
  // 「全選択」のチェック状態を切替える
  if ($('#items :checked').length == $('#items :input').length){
    $('#check_all').prop('checked', true);
  }else{
    $('#check_all').prop('checked', false);
  }
});

各選択肢をチェックしたとき、選択肢のチェックボックス数と、チェック状態の数を比較します。

  • 数が同数    :「すべて」をチェック状態にします。 => .prop('checked', true)
  • 数が同数ではない:「すべて」のチェックを外します。  => .prop('checked', false)

チェックした値を配列で取得

.each() を使用

JavaScript
$('#get_values').on('click', function() {

  var vals = []; // 配列を定義
  $('input[name="fruits"]:checked').each(function() {
      vals.push( $(this).val() ); // 配列に値を追加
  });

  console.log(vals);
});

チェック済みのinput要素を.each()対象にするので、
input[name="name属性名"]:checkedのように、セレクタに:checkedを付けます。

チェック済みの値を格納する配列valsを定義しておき、.push()で追加しましょう。

実行結果(ボタンをクリック)
// 「りんご」と「オレンジ」のみチェック
["apple", "orange"]

ボタンを押せば、チェック済みの値が配列で取得できます。

.map() を使用

JavaScript
$('#get_values').on('click', function(){

  var vals = $('input[name="fruits"]:checked').map(function() {
    return $(this).val();
  }).get();

  console.log(vals);
});

.map()を使用しても、実行結果は.each()と同じです。

完成(サンプル)

最後に完成形の全体コードを載せておきます。(.map()版)

<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="utf-8">
<title>全選択したチェックボックスの値を配列で取得するサンプル</title>
<script src="https://code.jquery.com/jquery-3.4.1.min.js"></script>
<script>
$(function() {
  // チェックボックスの全選択・解除
  $('#check_all').on('change', function() {
    // 「選択肢」のチェック状態を切替える
    $('.item').prop('checked', $(this).is(':checked'));
  });

  $('.item').on('change', function() {
    // 「全選択」のチェック状態を切替える
    if ($('#items :checked').length == $('#items :input').length){
      $('#check_all').prop('checked', true);
    }else{
      $('#check_all').prop('checked', false);
    }
  });


  // チェックした値を配列で取得
  $('#get_values').on('click', function(){

    var vals = $('input[name="fruits"]:checked').map(function() {
      return $(this).val();
    }).get();

    console.log(vals);
  });
});
</script>
</head>
<body>
  <!-- 全選択 -->
  <label><input type="checkbox" id="check_all" name="check_all">すべて</label>

  <!-- 選択肢 -->
  <div id="items">
    <label><input type="checkbox" name="fruits" value="apple" class="item">りんご</label>
    <label><input type="checkbox" name="fruits" value="banana" class="item">バナナ</label>
    <label><input type="checkbox" name="fruits" value="grapes" class="item">ぶどう</label>
    <label><input type="checkbox" name="fruits" value="orange" class="item">オレンジ</label>
    <label><input type="checkbox" name="fruits" value="strawberry" class="item">いちご</label>
  </div>

  <!-- ボタン -->
  <input type="button" value="チェックボックスの値を配列で取得" id="get_values">
</body>
</html>
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

P5.js 日本語リファレンス(bezierDetail)

このページでは「P5.js 日本語リファレンス」 の bezierDetail関数を説明します。

bezierDetail()

説明文

bezier曲線が表示される解像度を設定します。

デフォルト値は20です。

この関数はcreateCanvas()で WEBGL を指定した場合のみ有効です。

構文

bezierDetail(detail)

パラメタ

  • detail
    Number:曲線の解像度

例1

function setup(){
   createCanvas(100, 100, WEBGL);
   noFill();
   bezierDetail (8); // 曲線の描画を少し粗くする
}

function draw(){
   bezier(-40, -40, 0,
             90, -40, 0,
            -90,  40, 0,
             40,  40, 0);
}

実行結果

bezierDetail.png

著作権

p5.js was created by Lauren McCarthy and is developed by a community of collaborators, with support from the Processing Foundation and NYU ITP. Identity and graphic design by Jerel Johnson.

ライセンス

Creative Commons(CC BY-NC-SA 4.0) に従います。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

P5.js 日本語リファレンス(bezier)

このページでは「P5.js 日本語リファレンス」 の bezier関数を説明します。

bezier()

説明文

3次ベジェ曲線を描画します。これらの曲線は、 一連のアンカーポイントとコントロールポイントによって定義されます。最初の2つのパラメーターは最初のアンカーポイントを指定し, 最後の2つのパラメーターは他のアンカーポイントを指定します。これらは, 曲線の最初と最後のポイントになります。中央のパラメータは, 曲線の形状を定義する2つの制御点を指定します。近似的に言えば, コントロールポイントはカーブをその方向に「引き」ます。

ベジエ曲線はフランスの自動車技術者ピエールベジエによって開発され, 緩やかに傾斜した曲線を定義するためにコンピュータグラフィックスで一般的に使用されています。 curve()もご覧ください。

構文

bezier(x1, y1, x2, y2, x3, y3, x4, y4)

bezier(x1, y1, z1, x2, y2, z2, x3, y3, z3, x4, y4, z4)

パラメタ

  • x1

    Number:最初のアンカーポイントのx座標

  • y1

    Number:最初のアンカーポイントのy座標

  • x2

    Number:最初の制御点のx座標

  • y2

    Number:最初の制御点のy座標

  • x3

    Number:2番目の制御点のx座標

  • y3

    Number:2番目の制御点のy座標

  • x4

    Number:2番目のアンカーポイントのx座標

  • y4

    Number:2番目のアンカーポイントのy座標

  • z1

    Number:最初のアンカーポイントのZ座標

  • z2

    Number:最初の制御点のz座標

  • z3

    Number:2番目の制御点のz座標

  • z4

    Number:2番目のアンカーポイントのZ座標

例1

function draw() {
  noFill();
  stroke(255, 0, 0); // 赤色を指定
  line(10, 10, 85, 10); // 上の線を描画
  line(15, 80, 90, 80); // 下の線を描画
  stroke(0, 0, 0); // 黒色を指定
  bezier(85, 10, 10, 10, 90, 90, 15, 80); // 右上から左下に bezier 曲線を描画
}

実行結果

bezier-1.png

例2

function draw() {
  background(0, 0, 0);
  noFill();
  stroke(255); // 白色を指定
  bezier(150, 150, 0, 100, 100, 0, 100, 0, 0, 0, 100, 0); // 下から上に bezier 曲線を描画
}

実行結果

bezier-2.png

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

サイト構築のタスクを自動化する「Gatsby Recipes」とタスク記述言語としてのMDX

2020年4月、Reactでウェブサイトやアプリケーションを作るGatsbyから「Gatsby Recipes」の発表がありました。(執筆時点ではまだExperimentalな機能です)

Gatsby RecipesはGatsbyでサイトを制作する際に利用するようなタスクを自動化するものです。上記のツイートのようにCLIを経由して使います。
次のようなタスクを自動化します。

  • ページやレイアウトの作成
  • プラグインのインストールと設定
  • TypeScriptの設定

利用するにはGatsbyプロジェクト内で次のコマンドを入力しgatsby, gatsby-cliを最新のものにしてください。

npm install -g gatsby-cli@latest
npm install gatsby@latest

インストールを終えたら、gatsby recipesと入力することで、利用できるレシピを選択できます。
前もって、利用したいレシピが決まっている場合gatsby recipes styled-componentsのように指定が可能です。

レシピを決定すると、ウィザードに従って操作を行うとレシピが実行されます。ライブラリのインストールやgatsby-configの書き換え、必要なファイルの生成などを行ってくれます。

MDXを使ったタスクの記述

Gatsby Recipesは単にサイト構築の支援ツールのように見えますが、一番おもしろいところは上記のようなタスクを記述するのにMDX(Markdown + JSX)を利用しているところです。

MDXはMarkdown内でJSXを仕様できるようにしたフォーマットです。
MDXを使った代表的なものにjxnblk/mdx-deckというスライドツールがあります。MarkdownとJSXを利用してプレゼンテーションを作っていくツールです。

冒頭のツイートのレシピは次のようなMDXを元に動作しています。

 # Setup Theme UI

 This recipe helps you start developing with the [Theme UI](https://theme-ui.com) styling library.

 <Config name="gatsbyjs/add-theme-ui" />

 ---

 Install packages.

 <NPMPackage name="theme-ui" />
 <NPMPackage name="gatsby-plugin-theme-ui" />
 <NPMPackage name="@theme-ui/presets" />

 ---

 Add the plugin `gatsby-plugin-theme-ui` to your `gatsby-config.js`.

 <GatsbyPlugin name="gatsby-plugin-theme-ui" />

 ---

 Write out Theme UI configuration files.

 <File
   path="src/gatsby-plugin-theme-ui/index.js"
   content="https://gist.github.com/KyleAMathews/ab59e200e4f8a1b4109dddb51b2140f9/raw/209a2e7c589766869522b12f7f6cecaf3f7a6f81/index.js"
 />

 <File
   content="export default {}"
   path="src/gatsby-plugin-theme-ui/components.js"
 />

 ---

 **Success**!

 You're ready to get started!

 - Read the docs: https://theme-ui.com
 - Learn about the theme specification: https://system-ui.com

 *note:* if you're running this recipe on the default starter (or any other starter with
 base css), you'll need to remove the require to `layout.css` in the `components/layout.js` file
 as otherwise they'll override some theme-ui styles.

見てわかる通り、Markdownで記述した箇所が文章として、JSXで表示されている部分が実際に実行されている構造になります。
以前からタスク自動化のツールはありましたが、人間に優しくない記述や自由度が低いものが多く存在しました。その課題をうまく解決しようとしている点でGatsby Recipesは非常に面白い試みでしょう。

Recipesに見るNext.jsとの棲み分け

ここからは自分の見解になります。
つい最近、同じくReactをベースにしたフレームワークのNext.js 9.3が公開されました。Next.js 9.3ではStaticにデータを扱う部分が強化され、一見してGatsbyとNext.jsの差が小さくなっています。
しかし、Next.jsは大体何でも作れる万能ナイフ的なフレームワークである一方、Gatsbyは(アプリケーションも作れますが)ウェブサイトに特化したフレームワークです。ウェブサイトに特化している分、プラグインやスターター(テンプレート)が使いやすくエコシステムも強大です。

Gatsby Recipesは一般的なタスクに対応し、よりGatsbyのセットアップは簡単になっていきます。また、RFC段階ではありますが、GatsbyのサイトをいじるためのUI「Gatsby Admin」の動きもあります。これは何でも作れるNext.jsには作りにくく、ウェブサイトに特化したGatsbyだから出来る取り組みです。


Gatsbyは登場して5年ほどたって成熟しているような印象も受けますが、よりよいDXで開発が出来るような方向でさらなる進化をしています。
興味を持った方はGatsby Reciepesはもちろん、Gatsby Adminへ目を向けてみてはいかがでしょうか?

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

P5.js 日本語リファレンス(p5.Color)

このページでは「P5.js 日本語リファレンス」 の p5.Colorを説明します。

p5.Color

説明文

各色は指定したカラーモードとレベルの最大値で格納します。

内部的には、理想的なRGBA値を表す配列を0から1に正規化した浮動小数点形式で格納します。そして、最も近い画面色 ( 0から​​255までのRGBAレベル ) を計算しこれを画面表示します。

また、色の正規化された浮動小数点データは, 計算時にさまざまな表現でキャッシュされます。これは、すでに実行された変換を繰り返すのを防ぐために行われます。

構文

new p5.Color()

メソッド

  • toString()

    この関数は、文字列としてフォーマットされた色を返します。これは、デバッグや、他のライブラリでp5.jsを使用する場合に役立ちます。

  • setRed()

    setRed関数は、赤色を設定します。範囲はカラーモードによって異なりますが、デフォルトのRGBモードでは0〜255です。

  • setGreen()

    setGreen関数は、緑色を設定します。範囲はカラーモードによって異なりますが、デフォルトのRGBモードでは0〜255です。

  • setBlue()

    setBlue関数は、青色を設定します。範囲はカラーモードによって異なりますが、デフォルトのRGBモードでは0〜255です。

  • setAlpha()

    setAlpha関数は、色の透明度 ( アルファ ) 値を設定します。範囲はカラーモードによって異なりますが、デフォルトのRGBモードでは0〜255です。

著作権

p5.js was created by Lauren McCarthy and is developed by a community of collaborators, with support from the Processing Foundation and NYU ITP. Identity and graphic design by Jerel Johnson.

ライセンス

Creative Commons ( CC BY-NC-SA 4.0 ) に従います。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

P5.js 日本語リファレンス(saturation)

このページでは「P5.js 日本語リファレンス」 の saturation関数を説明します。

saturation()

説明文

指定した色から彩度値を抽出します。

HSBとHSLでは, 彩度のスケーリングが異なります。この関数は、HSBカラーを指定した場合にHSB彩度値を返しますが、それ以外の場合はデフォルトでHSL彩度値を返します。

構文

saturation(color)

パラメタ

  • color
    p5.Color | Number[ ] | String:p5.Colorオブジェクト、カラーコンポーネント、CSSカラー

戻り値

Number:彩度値

function draw() {
  colorMode(HSB, 255); // カラーモードをHSBに設定
  let c = color(0, 190, 255);
  fill(c);
  rect(15, 20, 35, 60);
  value = saturation(c); // 彩度値190を取得する
  fill(value);
  rect(50, 20, 35, 60);
}

実行結果

saturation.JPG

著作権

p5.js was created by Lauren McCarthy and is developed by a community of collaborators, with support from the Processing Foundation and NYU ITP. Identity and graphic design by Jerel Johnson.

ライセンス

Creative Commons(CC BY-NC-SA 4.0) に従います。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

P5.js 日本語リファレンス(lightness)

このページでは「P5.js 日本語リファレンス」 の lightness関数を説明します。

lightness()

説明文

指定した色からHSL明度値を取得します。

構文

lightness(color)

パラメタ

  • color
    p5.Color | Number[ ] | String:p5.Colorオブジェクト、カラーコンポーネント、CSSカラー

戻り値

Number:HSL明度値

function draw() {
  colorMode(HSL);
  let c = color(156, 100, 50, 1); // 緑色を設定
  fill(c);
  rect(15, 20, 35, 60);
  let value = lightness(c); // HSL明度値50を取得します
  fill(value);
  rect(50, 20, 35, 60);
}

実行結果

lightness.JPG

著作権

p5.js was created by Lauren McCarthy and is developed by a community of collaborators, with support from the Processing Foundation and NYU ITP. Identity and graphic design by Jerel Johnson.

ライセンス

Creative Commons(CC BY-NC-SA 4.0) に従います。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

P5.js 日本語リファレンス(lerpColor)

このページでは「P5.js 日本語リファレンス」 の lerpColor関数を説明します。

lerpColor ()

説明文

2つの色をブレンドしてそれらの間にある中間色を取得できます。 amtパラメータは2つの値の間を補間する量です。0.0は開始の色に等しく、0.1は開始の色に非常に近く、0.5はその中間などです。0未満の値は0として扱われ、1以上の値は1として扱われます。

色が補間される方法は、現在のカラーモードによって異なります。

構文

lerpColor(c1, c2, amt)

パラメタ

  • c1
    p5.Color:補間を開始する色

  • c2
    p5.Color:補間を終了する色

  • amt
    Number:0と1の間の数

戻り値

p5.Color: amt の位置する中間色

function draw() {
  let from = color(200, 00, 0); // 赤色を設定
  let to = color(0, 0, 200); // 青色を設定
  colorMode(RGB);
  let interA = lerpColor(from, to, 0.33); // 1/3地点での補完色
  let interB = lerpColor(from, to, 0.66); // 2/3地点での補完色
  fill(from);
  rect(10, 20, 20, 60);
  fill(interA);
  rect(30, 20, 20, 60);
  fill(interB);
  rect(50, 20, 20, 60);
  fill(to);
  rect(70, 20, 20, 60);
}

実行結果

lerpColor.JPG

著作権

p5.js was created by Lauren McCarthy and is developed by a community of collaborators, with support from the Processing Foundation and NYU ITP. Identity and graphic design by Jerel Johnson.

ライセンス

Creative Commons(CC BY-NC-SA 4.0) に従います。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

P5.js 日本語リファレンス(hue)

このページでは「P5.js 日本語リファレンス」 の hue関数を説明します。

hue()

説明文

指定した色から色相値を取得します。

色相はHSBとHSLの両方に存在します。この関数はHSBカラーを指定した場合にHSBの色相値を返しますが、それ以外の場合はデフォルトでHSLの色相値を返します。 (返す色相値は最大色相設定により異なります)

構文

hue(color)

パラメタ

  • color
    p5.Color | Number[ ] | String:p5.Colorオブジェクト、カラーコンポーネント、CSSカラー

戻り値

Number:色相値

function draw() {
  colorMode(HSB, 255); // カラーモードをHSBに設定
  let c = color(180, 126, 255);
  fill(c);
  rect(15, 20, 35, 60);
  value = hue(c); // 色相値180を取得する
  fill(value);
  rect(50, 20, 35, 60);
}

実行結果

hue.JPG

著作権

p5.js was created by Lauren McCarthy and is developed by a community of collaborators, with support from the Processing Foundation and NYU ITP. Identity and graphic design by Jerel Johnson.

ライセンス

Creative Commons(CC BY-NC-SA 4.0) に従います。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

P5.js 日本語リファレンス(color)

このページでは「P5.js 日本語リファレンス」 の color関数を説明します。

color()

説明文

colorデータ型の変数に格納する色を作成します。 パラメータは現在のcolorMode() に応じてRGBまたはHSB値として解釈されます。 デフォルトモードは0〜255のRGB値であるため、関数呼び出しcolor(255, 204, 0)は明るい黄色を返します。

color() に提供される値が1つだけの場合、それはグレースケール値として解釈されます。 2番目の値を追加するとアルファ透明度に使用されます。 3つの値が指定されるとそれらはRGBまたはHSB値として解釈されます。 4番目の値を追加するとアルファ透明度が適用されます。

単一の文字列引数が指定されている場合, RGB, RGBA, および16進数のCSSカラー文字列とすべての名前付きカラー文字列がサポートされます。 この場合, 2番目の引数としてのアルファ値はサポートされていません。RGBA形式を使用する必要があります。

function draw() {
  colorMode(RGB);
  let c = color(255, 204, 0); // RGBで黄色を指定
  fill(c); 
  rect(30, 20, 55, 55); 

  c = color(90); // グレー色を指定
  fill(c);
  ellipse(100, 75, 80, 80);

  c = color('blue'); // 名前付きカラー文字列で blue を指定
  fill(c);
  rect(160, 20, 60, 60);

  c = color('#00ff00'); // 16進数のCSSカラー文字列で緑色を指定
  fill(c);
  rect(200, 60, 45, 80);

  colorMode(HSB, 100); // カラーモードをHSBに設定
  c = color('hsb(0, 80%, 100%)'); // HSBで赤色を指定
  fill(c);
  rect(270, 10, 45, 80);

  c = color('hsba(160, 100%, 90%, 0.5)'); // HSBでアルファ透明度付きの緑色を指定
  fill(c);
  rect(300, 60, 45, 80);
}

実行結果

color.JPG

著作権

p5.js was created by Lauren McCarthy and is developed by a community of collaborators, with support from the Processing Foundation and NYU ITP. Identity and graphic design by Jerel Johnson.

ライセンス

Creative Commons(CC BY-NC-SA 4.0) に従います。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

P5.js 日本語リファレンス(brightness)

このページでは「P5.js 日本語リファレンス」 の brightness関数を説明します。

brightness ( )

説明文

HSB輝度値を指定した色から取得します。

構文

brightness ( color )

パラメタ

color
p5.Color | Number[ ] | String:p5.Colorオブジェクト、カラーコンポーネント、CSSカラー

戻り値

Number:明るさの値(HSB輝度値)

function draw() {
  noStroke();
  colorMode(HSB, 100); // カラーモードをHSBに設定
  let c1 = color(30, 100, 80); // HSBで緑色を設定
  fill(c1);
  rect(15, 20, 35, 60);
  let val1 = brightness(c1); // 輝度値80を取得する
  fill(val1);
  rect(50, 20, 35, 60);

  noStroke();
  colorMode(HSB, 255);
  let c2 = color('hsb(90, 100%, 80%)'); // HSBで緑色を設定
  fill(c2);
  rect(100, 20, 35, 60);
  let val2 = brightness(c2); // 輝度値80%(255の80%)を取得する
  fill(val2);
  rect(135, 20, 35, 60);
}

実行結果

brightness.JPG

著作権

p5.js was created by Lauren McCarthy and is developed by a community of collaborators, with support from the Processing Foundation and NYU ITP. Identity and graphic design by Jerel Johnson.

ライセンス

Creative Commons ( CC BY-NC-SA 4.0 ) に従います。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

P5.js 日本語リファレンス(blue)

このページでは「P5.js 日本語リファレンス」 の blue関数を説明します。

blue()

説明文

指定した色から青の値を取得します。

構文

blue(color)

パラメタ

  • color
    p5.Color | Number[ ] | String:p5.Colorオブジェクト、カラーコンポーネント、CSSカラー

戻り値

Number:青の値

function draw() {
  let c = color(255, 0, 255); // RGBで紫色を設定
  fill(c);
  rect(15, 20, 35, 60); //左の長方形を描画する

  let blueValue = blue(c); // 青色を取得する
  fill(0, 0, blueValue);
  rect(50, 20, 35, 60); // 右の長方形を描画する
}

実行結果

blue.JPG

著作権

p5.js was created by Lauren McCarthy and is developed by a community of collaborators, with support from the Processing Foundation and NYU ITP. Identity and graphic design by Jerel Johnson.

ライセンス

Creative Commons(CC BY-NC-SA 4.0) に従います。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

P5.js 日本語リファレンス(green)

このページでは「P5.js 日本語リファレンス」 の green関数を説明します。

green()

説明文

指定した色から緑の値を取得します。

構文

green()

パラメタ

  • color
    p5.Color | Number[ ] | String:p5.Colorオブジェクト、カラーコンポーネント、CSSカラー

戻り値

Number:緑の値

function draw() {
  let c = color(255, 255, 0); // RGBで黄色を設定
  fill(c );
  rect(15, 20, 35, 60 );

  let greenValue = green(c); // 緑色を取得する
  fill(0, greenValue, 0);
  rect(50, 20, 35, 60);
}

実行結果

green.JPG

著作権

p5.js was created by Lauren McCarthy and is developed by a community of collaborators, with support from the Processing Foundation and NYU ITP. Identity and graphic design by Jerel Johnson.

ライセンス

Creative Commons(CC BY-NC-SA 4.0) に従います。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

P5.js 日本語リファレンス(red)

このページでは「P5.js 日本語リファレンス」 の red関数を説明します。

red()

説明文

指定した色から赤の値を取得します。

構文

red(color)

パラメタ

  • color
    p5.Color | Number[ ] | String:p5.Colorオブジェクト、カラーコンポーネント、CSSカラー

戻り値

Number:赤の値

function draw() {
  let c = color('#FFFF00'); // CSSカラーで黄色を設定
  fill(c);
  rect(15, 20, 35, 60); //左の長方形を描画する

  let redValue = red(c); // 赤色を取得する
  fill(redValue, 0, 0);
  rect(50, 20, 35, 60); // 右の長方形を描画する
}

実行結果

red.JPG

著作権

p5.js was created by Lauren McCarthy and is developed by a community of collaborators, with support from the Processing Foundation and NYU ITP. Identity and graphic design by Jerel Johnson.

ライセンス

Creative Commons(CC BY-NC-SA 4.0) に従います。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む