- 投稿日:2020-10-17T22:58:38+09:00
【Vue.js】リアクティブに画像プレビューする
new FileReaderについて
アップロード画像を非同期に読み取ることができるオブジェクト
const reader = new FileReader();FileReaderでできること
読み込まれた画像情報をアップロード画像データに上書きする
reader.onload = (e) => { this.staff_image = e.target.result; };アップロード画像を読み込む
reader.readAsDataURL(this.staff_image);
- 読み取り操作が正常に完了されたら、result属性に格納されたデータを、アップロード画像データに上書きする
- アップロード画像を読み込ませた結果をresult属性に返している
実践:アップロード画像をプレビューで表示させて、DBに保存する
ポイント
- プレビュー画像と、DB保存画像の格納dataを分けて考える
流れ
- v-input-fileに、v-model属性をつけることで、アップロードファイルとdataオプションと連動させる
- 画像がアップロードされたらimgaeUp関数が着火し、画像ファイル拡張子を使えるものに限定させる。この時、DBに保存する画像情報を格納しておく。
- もし使えない画像拡張の場合は、errors変数にエラー文を格納すると共に画像情報を削除し、imageUp関数を強制終了させる
- 特に問題ない場合、プレビュー画像用に画像情報をパースし、アップロード画像を表示させる判定に切り替える。
tmplateタグ(pug形式)
v-img(v-if="image", :src="staff_image") v-img(v-else, src="/images/default.png")v-file-input( hide-input, // フォームを隠す prepend-icon="mdi-camera", // ボタンアイコン @change="imageUp()", // アップロードされたら、着火する関数 v-model="staff_image" // アップロード画像と連動させる )scriptタグ
data() { return { staff_image: "", // アップロードファイルの格納場所 image_name: "", // DBに保存するアップロードファイル image: false, // 表示するのは、デフォルト画像かアップロード画像かの判定 }; }, imageUp() { // 画像ファイル拡張子の検証 const type = this.staff_image.type; this.image_name = this.staff_image; // DB保存用に、画像情報を格納しておく let errors = ""; if ( type !== "image/jpeg" && type !== "image/gif" && type !== "image/png" && type !== "application/pdf" ) { errors += ".jpg、.gif、.png、.pdfのいずれかのファイルのみ許可されています\n"; } if (errors) { alert(errors); this.staff_image = ""; this.image_name = ""; this.image = false; return; // エラー処理の場合、imageUp関数を強制終了する } // アップロード画像をプレビューで表示させる const reader = new FileReader(); reader.onload = (e) => { this.staff_image = e.target.result; }; reader.readAsDataURL(this.staff_image); this.image = true; // アップロード画像の表示に切り替える },
- 投稿日:2020-10-17T22:30:02+09:00
温度センサーとLEDで室温をぱっと見で分かるものを作ってみた
目的
温度センサーとLEDを使ってみたかったので、2つを同時に使って色で室温がぱっとわかるものを作ってみました。
実現方法
使用したもの
・obniz Board 1Y
・高精度IC温度センサー LM60BIZ
・マイコン内蔵RGB 8mmLED PL9823-F8ロジック
個人的には25℃をより下だと涼しい、25℃より上だと暖かいだと感じているので
温度センサーで取得した温度が25℃より大きい場合、オレンジ
それ以外の場合、水色
にしました。
obnizへは
温度センサー 0、1、2 へ接続
LED 9、10、11 へ接続
しています。実際に動かしてみた
実際に動かした動画をTwitterにあげてます!
※温度センサーに指を近づけて、温度をわざとあげました。
温度センサーとLEDを組み合わせてみました!#obniz #protoout pic.twitter.com/r4dY4U0bHI
— heihei (@heihei15408697) October 17, 2020コード
const Obniz = require('obniz'); const obniz = new Obniz('ObnizのID'); // Obniz_IDに自分のIDを入れてください obniz.onconnect = async function () { // 温度センサの利用 const tempsens = obniz.wired('LM60', { gnd: 0, output: 1, vcc: 2 }); // RGB LEDを利用 const rgbled = obniz.wired('WS2811', { gnd: 9, vcc: 10, din: 11 }); // setIntervalで間隔を作る setInterval(async function () { // 同期で取得 const temp = await tempsens.getWait(); if (temp>25) { // オレンジ rgbled.rgb(255, 165, 0); } else { // 水色 rgbled.rgb(0, 191, 250); } // ターミナル表示 console.log('obniz temp:', temp); // 温度をコンソールに表示 console.log(temp); // obnizディスプレイ表示 obniz.display.clear(); obniz.display.print(temp + 'C'); }, 10000); // 10000ミリ秒 = 10秒 }考察
最初は温度センサーとLEDを組み合わせるのはハードル結構高いのかなと思ったのですが、obnizを使うと簡単にできることを体験することができました!(2時間くらいで出来ました!)
・今は25℃固定ですが、徐々にLEDの色を変えていく
・LINEなどのツールを使って、温度確認したときに色がでるようにする
などいろいろ発展させていければと思っています!
- 投稿日:2020-10-17T21:50:51+09:00
【初心者でもわかる】<form>タグを外から動かす2つの方法
どうも7noteです。formタグのプチ応用の使い方について。
html要素の
<form>
タグは、タグで囲まれた中のinputやselectの値をgetやpostで受け渡すことができます。
通常の使い方であれば、タグに囲まれた中にある<button>
タグやを使って動かすのですが、今回は<form>
タグの外から、formを動かして値の受け渡しを行います。方法1 HTMLのみでできる方法
<button>
要素を作成し、そのform属性に動かしたい<form>
のidを指定。form.html<form id="mainform" action="" method="post"> <input type="text" value=""> </form> <button type="submit" form="mainform">送信する</button> <!-- form属性に、動かしたい<form>のidを指定。 -->これで、
<form>
外からもsubmit(送信)することができます。方法2 クリックやチェックなどのアクションした時に動作させる方法
javascriptを使用します。今回はjQueryも使用しています。
以下の例はクリックされた時の場合の書き方。form.html<form id="mainform" action="" method="post"> <input type="text" value=""> </form> <div class="btn">送信する</div> <script> $(".btn").on("click", function(e){ // クラスbtnがクリックされた時 document.forms.mainform.submit(); // mainformをsubmit(送信)する )}; </script>関数を作る方法であれば以下のような書き方もできます。
form.html<form id="mainform" action="" method="post"> <input type="text" value=""> </form> <div class="btn" onclick="clickEvent();">送信する</div> <!-- onclick属性で動かすjsを指定 --> <script> function clickEvent(){ document.forms.mainform.submit(); // mainformをsubmit(送信)する } </script>javascriptで書くメリットは、送信ボタンを押された瞬間に他の処理を動かしたり、条件分岐して動かすformを切り換えたり、値を入れなおしたりできるところです。
ややこしい処理が必要な場面でも対応が可能です。
また、前者の方法であれば、clickを別のものに変えることで、値が変更されたときや、他の任意のタイミングで動かすことができます。まとめ
HTMLだけでできる方法もありますが、しっかりと作りこんだサイトで細かい動きも入れるのであればjavascriptを使った動かし方の方をおすすめします。
簡易的でシンプルなフォームであれば、HTMLだけの方法で十分対応できると思います!おそまつ!
~ Qiitaで毎日投稿中!! ~
【初心者向け】HTML・CSSのちょいテク詰め合わせ
- 投稿日:2020-10-17T21:47:46+09:00
slack botからメールアドレスを利用してDMを送りたい!
この記事に書いてある事
- メールアドレスを利用して、slack botからDMを送る
- GASで実装
- ハマりポイント
- まとめ
1. メールアドレスを利用して、slack botからDMを送る
ゴール
testというbotの権限を持っているslack appからDMを送るようにしました。
DMを送る対象は、メールアドレスをスプレットシートで管理してます。構成
2. GASで実装
処理の流れ
- spread sheetから対象のメールドレス一覧取得
- slack apiでslackのuser id取得(member idともいう)
- slack apiでDMを送れる状態にする
- slack apiでDM送信
サンプルコード
- spread sheetから対象のメールドレス一覧取得
function getRequiredMailList () { let member_list_sheet_id = $spread_sheet_id let sheet = SpreadsheetApp.openById(member_list_sheet_id).getSheetByName($シート名) var lastRow = sheet.getLastRow(); // Note: 空白の行は要らないから、入力のある行の最後の行を取得 return sheet.getRange(1, 1, lastRow, 1).getValues().map(row => row[0]) //Note: 行, 列, 何行, option何列 }2.slack apiでslackのuser id取得(member idともいう)
const token = PropertiesService.getScriptProperties().getProperty('SLACK_ACCESS_TOKEN'); // Note: 環境変数にTOKEN保存しておいてね var userInfoUrl = 'https://slack.com/api/users.lookupByEmail?token=' + token + '&email=' + email + '&pretty=1' const userId = JSON.parse(UrlFetchApp.fetch(userInfoUrl)).user.id3.slack apiでDMを送れる状態にする
// Note: userIdは ☝️ 2 で取得したものを利用 const url = 'https://slack.com/api/conversations.open?token=' + token + '&users=' + userId + '&pretty=1' const channel = JSON.parse(UrlFetchApp.fetch(url)).channel4.slack apiでDM送信
const messageOptions = { "method" : "post", "contentType": "application/x-www-form-urlencoded", "payload" : { "token": token, "channel": channel.id, // Note: channelは ☝️ 3 で取得したものを利用 "text": "DMで送りたい内容はここに書くよ〜" } }; var result = UrlFetchApp.fetch('https://slack.com/api/chat.postMessage', messageOptions);完成
3. ハマりポイント
botの権限系
何の権限付ければ良いの問題
今回の構成なら、とりあえずこれをつけておけばオケ ごにょごにょしまくってたから、もしかしたら不要なのもあるかも。
言われた権限付けても、変わらず同じエラーなんですけど問題
Reinstall Appをする!
権限をいじったら、毎回Reinstall Appをしないと反映されないから超注意
(ポエム) ここら辺に赤文字で大きく、「権限変えたらReinstall Appしてね!!」って書いておいて欲しかった。(めっちゃハマった)
社員のmemberIdどうやって知るんだ問題
課題
DMを送るためには、slackのmember IDを知る必要があります。
@erikaadno とかのメンションとは別に、slackのアカウントがある人全員に割り振られてるIDのこと。
「View Full Profile」から飛んだ、これ
ソリューション
lookupByEmailというslack apiを使います。
画面上からだと、member idだけど、APIのresponseはuser idconst token = PropertiesService.getScriptProperties().getProperty('SLACK_ACCESS_TOKEN'); var userInfoUrl = 'https://slack.com/api/users.lookupByEmail?token=' + token + '&email=' + email + '&pretty=1' const userId = JSON.parse(UrlFetchApp.fetch(userInfoUrl)).user.id4. まとめ
- 権限変えてもaccess deniedで続けるの謎だから、本当にreinstall Appをしないと反映されないよって開発してる全員が何回も目に留まるところに書いておいて欲しい。
- slack apiはAPIドキュメントにtesterがあって直ぐに試せるので最高。
- 投稿日:2020-10-17T21:23:39+09:00
【Vue.js】 transitionを使用してfade-in, fade-out
【ゴール】
【Vue.js】 transitionを使用してfade-in, fade-out
【環境】
mac catarina 10.156
Vue.js v2.6.12
【実装】
■ifで条件分岐
■transition name="fade"で、fadeモードに
Helloworld.vue<template> <div> <h2>hi</h2> <button @click="show = !show">変更</button> <transition name="fade" > <p v-if="show">trasition</p> <transition> </div> <template> <script> export default ({ data(){ return { show: true } } }) </script> <style scoped> .fade-enter-active, .fade-leave-active { transion: opacity 0.5s; } .fade-enter, .fade-leave-to{ opacity: 0; } </style>以上
【まとめ】
■transitionでアニメーションを作成
■nameでアニメーションの種類を指定してあげる
■style内でtransitionの設定をする【オススメ記事】
■ 【Vue.js】クリック処理 @click
https://qiita.com/tanaka-yu3/items/e578cadf35a7bc024770■ 【Vue.js】 IF文・For文 条件分岐、繰り返し処理
https://qiita.com/tanaka-yu3/items/0ccf9a11525331b764de■ 【Vue.js】 vue-routerを利用してルーティング作成し画面遷移を!!
https://qiita.com/tanaka-yu3/items/1b1f5f2b2d9638f50d33
- 投稿日:2020-10-17T21:17:08+09:00
ArchiverがZIPに含めるファイルをフィルタする
NodeモジュールArchiverは、ディレクトリをZIP圧縮するとき、ZIPに含めるファイルをフィルタすることができます。
(できないと思い込んでて、普通にできた。。)ZIP圧縮するディレクトリ
以下のディレクトリをZIP圧縮するとします。
ZIP圧縮するディレクトリsomedir │ file1.txt │ ├─dir1 │ file2.jpg │ file3.txt │ └─dir2 file4.jpg file5.txtプログラム
プログラムは以下になります。
ディレクトリをZIP圧縮するためにdirectory
関数を使いますが、第3引数にフィルタする関数を渡せます。
フィルタする関数の引数には、ZIP圧縮に含めるフォルダ・ファイルのデータが渡されます。
このデータをみて、含める場合データを返し、含めない場合false
を返します。
サンプルでは拡張子.txt
のファイルを含めないようにしています。サンプルconst fs = require('fs') const path = require('path') const archiver = require('archiver') const output = fs.createWriteStream(__dirname + '/somedir.zip') const archive = archiver('zip', { zlib: { level: 9 } }) output.on('close', function() { console.log('finish') }) archive.pipe(output) archive.directory('somedir', 'somedir', filter) archive.finalize() function filter(entry) { if (path.extname(entry.name) === '.txt') { // zipに含めない場合falseを返す return false } else { // zipに含める return entry } }ZIP圧縮されたディレクトリの中身
ZIP圧縮されたディレクトリを解凍し、中身を見てみると、以下になります。
拡張子.txt
のファイルはZIPに含まれていません。解凍したディレクトリsomedir ├─dir1 │ file2.jpg │ └─dir2 file4.jpg非同期でフィルタできない
directory
関数に渡すフィルタ関数ですが、Promise
を返せません。
async
/await
が使えず、非同期でフィルタができません。
(これはちょい残念かも)
- 投稿日:2020-10-17T18:08:57+09:00
スタバのWiFiにログインするだけのスクリプト
一時間経つと切れてしまい繋ぎ直すのが面倒だったのでスクリプトにしました。
chrome拡張のScriptAutoRunnerに登録して自動で流れるようにしてます。$(() => { if (document.getElementById('button_next_page') != null) { document.getElementById('button_next_page').click() } if (document.getElementById('button_accept') != null) { document.getElementById('button_accept').click() } })
- 投稿日:2020-10-17T18:08:57+09:00
スタバのWiFiに自動ログインするだけのスクリプト
一時間経つと切れてしまい繋ぎ直すのが面倒だったのでスクリプトにしました。
chrome拡張のScriptAutoRunnerに登録して自動で流れるようにしてます。$(() => { if (document.getElementById('button_next_page') != null) { document.getElementById('button_next_page').click() } if (document.getElementById('button_accept') != null) { document.getElementById('button_accept').click() } })
- 投稿日:2020-10-17T16:56:40+09:00
JavaScriptのライブラリJQueryでイベント発火Ajax(非同期通信の場合)
前提
- 非同期通信
- Ruby.Rails
- 送信フォームが送信(sendボタン押すイベント発火)されたらカラーのパネルが追加させる実装を行うことを例にする。
- <例>発火すると右上に選択した色が非同期通信で表示される。
イベントが発火した際にあることが実行されるようにする
①何をきっかけに(イベントは何?)
②イベントきっかけにどんなとこを実行するかこの2つを考えながらコードを考える。
「今回は送信ボタンを押したら(イベント)カラーパネルが追加されることが実行される」
①送信ボタンを押すということは「フォームが送信された時」だと考える。
②イベントをきっかけにカラーパネルが表示されるにはいくつかの工程が必要だと考える。
→Ajaxを使用(データ関連の引き渡し)
→HTMLで変化後の見た目(イベント発火をきっかけに起こる一部見た目の変化)①何をきっかけに(イベント発火は何?)
きっかけ:フォームの送信
フォームにイベントをセットする。
「フォームのボタンを押した時」というのを記述。###.js(JavaScriptファイル)$(function(){ $(*****).on(*****, function(){ }) })フォームのクラスを $( )に入れて、
「.on」は押すという意味を加える。
「on( , 」のon( の後には何を押すのかをいれる。
今回は'submit'ボタンを入れた。<記述例>$(function(){ $('.js-form').on('submit', function(){ }) })また、console.logを用いてイベント発火しているか確認もしてみてください。
空いている行に記述して送信ボタンを押すことで確認できます。
<例>console.log("テスト")
などカッコに入れてみてください。
できていない時はエラーが出るはずです。
次に、フォーム送信を停止
今のままだとデフォルトの設定として、
フォーム送信と共に画面が今まで非同期通信ではない画面遷移(画面移動)してしまう。
通常設定は阻止する必要がある。
非同期通信を行うために、preventDefault()を使用する。###.js(JavaScriptファイル)$(*****).on(*****, function(e){ e.preventDefault() }) })この際も真ん中の空いている行にconsole.logを入れてエラーが出てないか確認してみてください。
②イベントきっかけにどんなとこを実行するか
- Ajaxを使用(データ関連の引き渡し)
- HTMLで変化後の見た目(イベント発火をきっかけに起こる一部見た目の変化)
Ajaxを使用(データ関連の引き渡し)
この後必要になる基本のコード
先ほどのコードに 「$.ajax({」から追加しています。javascripts/###.js$(function(){ $(*****).on(*****, function(e){ e.preventDefault() $.ajax({ url: 取得したリクエストURL, //同期通信でいう『パス』 type: 'POST', //同期通信でいう『HTTPメソッド』 data: 取得したFormData, dataType: 'json', processData: false, contentType: false }) }) })↑この記述を行っても遷移先のviewファイル(〇〇.json.jbuilder)を作成していないとエラーが出ます。
ここからは送信フィームをイベントとした例を元にみていきます。
<例>$(function() { $('.js-form').on('submit', function(e) { e.preventDefault(); // ここから下追加記述 let formData = new FormData(this); let url = $(this).attr('action'); $.ajax({ url: url, type: "POST", data: formData, dataType: 'json', processData: false, contentType: false }) }); });
「フォームに入力された値を受け取れるようにする記述をする」
FormData
フォームのデータの送信に使用。
new FormData(フォーム要素)とすることでFormDataを作成。
今回の場合オブジェクトの引数はthis。
イベントで設定したfunction内でthisを利用した場合は、
イベントが発生したノード要素を指す。
今回の場合は、js-formというクラスがついたフォームの情報を取得している。
IDなどでも取得できる。<例>のFormDataについてlet formData = new FormData(this);
attrメソッド
引数に指定した属性の値を取得することができる。
<例>のattrメソッドとurlについてlet url = $(this).attr('action');例では引数に'action'を指定しているので(ここではthis)from要素のaction属性の値が取得できる。
「/songs/3/songcolors」このパスがactionから取れてurlに入れられてる。
そのurlがAjaxのurlに関わってくるのだと思います。
「$.ajax」の部分に非同期通信に必要なオプションを設定
<例>$.ajaxからの記述$.ajax({ url: url, type: "POST", data: formData, dataType: 'json', processData: false, contentType: false })
オプション 内容 type HTTP通信の種類を記述する。通信方法は、GETとPOSTの2種類。 url リクエストを送信する先のURLを記述する。遷移先、パス data サーバに送信する値を記述する。今回はデータを格納したものが入る。 dataType サーバから返されるデータの型を指定する。 processData デフォルトではtrue。dataに指定したオブジェクトをクエリ文字列(例: msg.txt?b1=%E3%81%8B&b2=%E3%81%8D )に変換する役割。 contentType サーバにデータのファイル形式を伝えるヘッダ。FormDataをつかってフォームの情報を取得した時には必ずfalseにする。さらに詳しくはこちら。
HTMLで変化後の見た目(イベント発火をきっかけに起こる一部見た目の変化)
非同期通信の結果(ブラウザの見た目としての変化)として返ってくるデータは、done(function(data) { 処理 })の関数の引数で受け取る。
doneメソッドを使う。また、doneメソッドで受け取った引数( )を元に「function buildHTML〜」の後からHTMLを組み立てる。
javascripts/###.js$(function(){ //ここから下5行追記 function buildHTML(***jsファイル名***){ let html = `<*******> </*******>`//`から`の間にHTMLが入る。 return html; } $(*****).on(*****, function(e){ e.preventDefault() let formData = new FormData(this); //フォームからデータをとってくる場合この一文を必要とする。 let url = $(this).attr('action'); //フォームのアクションに指定されたものが必要になる場合この一文が必要。 $.ajax({ url: 取得したリクエストURL, //同期通信でいう『パス』 type: 'POST', //同期通信でいう『HTTPメソッド』 data: 取得したFormData, dataType: 'json', processData: false, contentType: false }) //ここから以下追記 .done(function(data){ let html = buildHTML(data); $('.***ボタンのクラス***').prop('disabled', false) //一度押すと押せなくなる送信ボタンを連続で押せるようにしている $('***元のHTMLに追加したい場所を指定***').prepend(html);//.prepend指定した要素の最初に、引数で指定した内容を追加 }) }) })doneメソッド
.when( ) は先に実行したい処理。
.done( ) は後で実行したい処理。
のように処理をいつしたいか設定できます。
$('.ボタンのクラス').prop('disabled', false)
disabled属性をfalseにする記述でsubmitボタンが押せないのをfalseで解除する。
function buildHTMLL( ){let html = `<****></****>return html;}
doneメソッドで受け取った引数( )を元にHTMLを組み立てる。
HTMLの組み立てはつど全く違っているのでここに記述しておりませんが自分のコードを例に置いておいきます。<例>HTMLの箇所をピックアップしたものfunction buildHTML(songcolor){ let html = `<li class="color-box" style="background-color:${songcolor.color}"></li>` return html; };検証ツールで追加したいHTMLを見てみるととてもわかりやすいのと、
データベースの情報を表示する際は${}を使用すること、
ここに持ってくる情報は対応するviweに作った.json.jbuilderに設定したことを思い出すとわかりやすいかも。
prependメソッド
元のHTMLのどの部分に追加するのかクラスなどを指定して決める。
指定した要素(クラスなど)の最初に足すことができる。
そのほかにも最後に足したりするメソッドなども存在する。
このように様々なメソッドを使用することで、
テキストボックス内をイベント後に空にしたり設定することができる。
イベント発火により実行することが実装できたら…
その実行ができなかった場合を想定する
javascripts/###.js$(function(){ function buildHTML(******){ let html = `<*******> </*******>` return html; } $(*****).on(*****, function(e){ e.preventDefault() let formData = new FormData(this); let url = $(this).attr('action'); $.ajax({ url: 取得したリクエストURL, type: 'POST', data: FormData, dataType: 'json', processData: false, contentType: false }) .done(function(data){ let html = buildHTML(data); $('.******').prop('disabled', false) $('******').prepend(html); }) //ここから以下追記 .fail(function(){ alert('error'); }); }) })failメソッド
サーバーエラーの場合にdoneではなくfailが呼び出される。
alertメソッド
アラートが呼び出される。('****')の中身の文字がアラートで表示される。
以上です!
これで非同期通信の作業は最後です。
ほかにも様々な設定ができるのでこればかりではないのですが、
一旦ここで終わります。
最後にひとこと
ここまでまとめてみて、
一つ一つの記述の意味がより理解できました。
ただ、実際に新たに自分のオリジナルのアプリを開発したからというのも合わさっていたことが
今回の理解につながったのだと思います。新たな疑問点や課題
- 非同期通信をする際の手順を自分で思い出しながら実装できるかの不安
- doneメソッドの引数であるHTMLの組み立て
- done後の様々な記述
- Ajax後の設定が他で応用できるのか
- 非同期通信以外にJavaScriptでできることがあるがどんな仕組みなのか
理解が深まっていても実装で使用できるか
また、まだまだ理解が追いついていない部分を学習していきたいと思います。
初めてJSみた時はこんなの読めないと思っていましたが
今は少し見慣れてパーツごとに見れるようになったのが嬉しいです。
最後まで読んでくださってありがとうございました!
ではまた〜
- 投稿日:2020-10-17T16:56:40+09:00
JavaScriptのライブラリJQueryでイベント発火Ajax(非同期通信を実装する場合)
前提
- 非同期通信
- Ruby.Rails
- 送信フォームが送信(sendボタン押すイベント発火)されたらカラーのパネルが追加させる実装を行うことを例にする。
- <例>発火すると右上に選択した色が非同期通信で表示される。
イベントが発火した際にあることが実行されるようにする
①何をきっかけに(イベントは何?)
②イベントきっかけにどんなとこを実行するかこの2つを考えながらコードを考える。
「今回は送信ボタンを押したら(イベント)カラーパネルが追加されることが実行される」
①送信ボタンを押すということは「フォームが送信された時」だと考える。
②イベントをきっかけにカラーパネルが表示されるにはいくつかの工程が必要だと考える。
→Ajaxを使用(データ関連の引き渡し)
→HTMLで変化後の見た目(イベント発火をきっかけに起こる一部見た目の変化)①何をきっかけに(イベント発火は何?)
きっかけ:フォームの送信
「フォームのボタンを押した時」というのを記述。
###.js(JavaScriptファイル)$(function(){ $(*****).on(*****, function(){ }) })フォームに設定したのクラス名を $( )に入れて、
「.on」で押すという意味を加える。
「on( , 」のon( の後には何を押すのかをいれる。
今回は'submit'ボタンを入れた。<記述例>$(function(){ $('.js-form').on('submit', function(){ }) })また、console.logを用いてイベント発火しているか確認もしてみてください。
空いている行に記述して送信ボタンを押すことで確認できます。
<例>console.log("テスト")
などカッコに入れてみてください。
できていない時は検証のコンソールでエラーが出るはずです。
次に、デフォルト設定の方のフォーム送信を停止
今のままだとデフォルトの設定として、
フォーム送信と共に画面が今まで通り(非同期通信ではなく)画面遷移(画面移動)してしまう。
通常設定は阻止する必要がある。
非同期通信を行うために、preventDefault()を使用する。###.js(JavaScriptファイル)$(*****).on(*****, function(e){ e.preventDefault() }) })この際も真ん中の空いている行にconsole.logを入れてエラーが出てないか確認してみてください。
②イベントきっかけにどんなとこを実行するか
- Ajaxを使用(データ関連の引き渡し)
- HTMLで変化後の見た目(イベント発火をきっかけに起こる一部見た目の変化)
Ajaxを使用(データ関連の引き渡し)
この後必要になる基本のコード
先ほどのコードに 「$.ajax({」から追加しています。javascripts/###.js$(function(){ $(*****).on(*****, function(e){ e.preventDefault() // ここから下追加記述 $.ajax({ url: 取得したリクエストURL, //同期通信でいう『パス』 type: 'POST', //同期通信でいう『HTTPメソッド』 data: 取得したFormData, dataType: 'json', processData: false, contentType: false }) }) })↑この記述を行っても遷移先のviewファイル(〇〇.json.jbuilder)を作成していないとエラーが出ます。
ここからは送信フィームをイベントとした例を元にみていきます。
<例>$(function() { $('.js-form').on('submit', function(e) { e.preventDefault(); // ここから下追加記述 let formData = new FormData(this); let url = $(this).attr('action'); $.ajax({ url: url, type: "POST", data: formData, dataType: 'json', processData: false, contentType: false }) }); });
「フォームに入力された値を受け取れるようにする記述をする」
FormData
フォームのデータの送信に使用。
new FormData(フォーム要素)とすることでFormDataを作成。
今回の場合オブジェクトの引数はthis。
イベントで設定したfunction内でthisを利用した場合は、
イベントが発生したノード要素を指す。
今回の場合は、js-formというクラスがついたフォームの情報を取得している。
IDなどでも取得できる。<例>のFormDataについてlet formData = new FormData(this);
attrメソッド
引数に指定した属性の値を取得することができる。
<例>のattrメソッドとurlについてlet url = $(this).attr('action');例では引数に'action'を指定しているので(ここではthis)from要素のaction属性の値が取得できる。
「/songs/3/songcolors」このパスがactionから取れてurlに入れられてる。
そのurlがAjaxのurlに関わってくるのだと思います。
「$.ajax」の部分に非同期通信に必要なオプションを設定
<例>$.ajaxからの記述$.ajax({ url: url, type: "POST", data: formData, dataType: 'json', processData: false, contentType: false })
オプション 内容 type HTTP通信の種類を記述する。通信方法は、GETとPOSTの2種類。 url リクエストを送信する先のURLを記述する。遷移先、パス data サーバに送信する値を記述する。今回はデータを格納したものが入る。 dataType サーバから返されるデータの型を指定する。 processData デフォルトではtrue。dataに指定したオブジェクトをクエリ文字列(例: msg.txt?b1=%E3%81%8B&b2=%E3%81%8D )に変換する役割。 contentType サーバにデータのファイル形式を伝えるヘッダ。FormDataをつかってフォームの情報を取得した時には必ずfalseにする。さらに詳しくはこちら。
HTMLで変化後の見た目(イベント発火をきっかけに起こる一部見た目の変化)
非同期通信の結果(ブラウザの見た目としての変化)として返ってくるデータは、done(function(data) { 処理 })の関数の引数で受け取る。
doneメソッドを使う。また、doneメソッドで受け取った引数( )を元に「function buildHTML〜」の後からHTMLを組み立てる。
javascripts/###.js$(function(){ //ここから下5行追記 function buildHTML(***jsファイル名***){ let html = `<*******> </*******>`//`から`の間にHTMLが入る。 return html; } $(*****).on(*****, function(e){ e.preventDefault() let formData = new FormData(this); //フォームからデータをとってくる場合この一文を必要とする。 let url = $(this).attr('action'); //フォームのアクションに指定されたものが必要になる場合この一文が必要。 $.ajax({ url: 取得したリクエストURL, //同期通信でいう『パス』 type: 'POST', //同期通信でいう『HTTPメソッド』 data: 取得したFormData, dataType: 'json', processData: false, contentType: false }) //ここから以下追記 .done(function(data){ let html = buildHTML(data); $('.***ボタンのクラス***').prop('disabled', false) //一度押すと押せなくなる送信ボタンを連続で押せるようにしている $('***元のHTMLに追加したい場所を指定***').prepend(html);//.prepend指定した要素の最初に、引数で指定した内容を追加 }) }) })doneメソッド
.when( ) は先に実行したい処理。
.done( ) は後で実行したい処理。
のように処理をいつしたいか設定できます。
$('.ボタンのクラス').prop('disabled', false)
disabled属性をfalseにする記述でsubmitボタンが押せないのをfalseで解除する。
function buildHTMLL( ){let html = `<****></****>return html;}
doneメソッドで受け取った引数( )を元にHTMLを組み立てる。
HTMLの組み立てはつど全く違っているのでここに記述しておりませんが自分のコードを例に置いておいきます。<例>HTMLの箇所をピックアップしたものfunction buildHTML(songcolor){ let html = `<li class="color-box" style="background-color:${songcolor.color}"></li>` return html; };検証ツールで追加したいHTMLを見てみるととてもわかりやすいのと、
データベースの情報を表示する際は${}を使用すること、
ここに持ってくる情報は対応するviweに作った.json.jbuilderに設定したことを思い出すとわかりやすいかも。
prependメソッド
元のHTMLのどの部分に追加するのかクラスなどを指定して決める。
指定した要素(クラスなど)の最初に足すことができる。
そのほかにも最後に足したりするメソッドなども存在する。
このように様々なメソッドを使用することで、
テキストボックス内をイベント後に空にしたり設定することができる。
イベント発火により実行することが実装できたら…
その実行ができなかった場合を想定する
javascripts/###.js$(function(){ function buildHTML(******){ let html = `<*******> </*******>` return html; } $(*****).on(*****, function(e){ e.preventDefault() let formData = new FormData(this); let url = $(this).attr('action'); $.ajax({ url: 取得したリクエストURL, type: 'POST', data: FormData, dataType: 'json', processData: false, contentType: false }) .done(function(data){ let html = buildHTML(data); $('.******').prop('disabled', false) $('******').prepend(html); }) //ここから以下追記 .fail(function(){ alert('error'); }); }) })failメソッド
サーバーエラーの場合にdoneではなくfailが呼び出される。
alertメソッド
アラートが呼び出される。('****')の中身の文字がアラートで表示される。
以上です!
これで非同期通信の作業は最後です。
ほかにも様々な設定ができるのでこればかりではないのですが、
一旦ここで終わります。
最後にひとこと
ここまでまとめてみて、
一つ一つの記述の意味がより理解できました。
ただ、実際に新たに自分のオリジナルのアプリを開発したからというのも合わさって
今回の理解につながったのだと思います。新たな疑問点や課題
- 非同期通信をする際の手順を自分で思い出しながら実装できるかの不安
- doneメソッドの引数であるHTMLの組み立て
- done後の様々な記述
- Ajax後の設定が他で応用できるのか
- 非同期通信以外にJavaScriptでできることがあるがどんな仕組みなのか
理解が深まっていても実装で使用できるか
また、まだまだ理解が追いついていない部分を学習していきたいと思います。
初めてJSみた時はこんなの読めないと思っていましたが
今は少し見慣れてパーツごとに見れるようになったのが嬉しいです。
最後まで読んでくださってありがとうございました!
ではまた〜
- 投稿日:2020-10-17T16:56:40+09:00
JavaScriptのライブラリJQueryでイベント発火・Ajax(非同期通信を実装する場合)
前提
- 非同期通信
- Ruby.Rails
- 送信フォームが送信(sendボタン押すイベント発火)されたらカラーのパネルが追加させる実装を行うことを例にする。
- <例>発火すると右上に選択した色が非同期通信で表示される。
イベントが発火した際にあることが実行されるようにする
①何をきっかけに(=イベントは何?)
②イベントきっかけにどんなとこを実行するかこの2つを考えながらコードを考える。
「今回は送信ボタンを押したら(イベント)カラーパネルが追加されることが実行される」
①送信ボタンを押すということは「フォームが送信された時」だと考える。
②イベントをきっかけにカラーパネルが表示されるにはいくつかの工程が必要だと考える。
→Ajaxを使用(データ関連の引き渡し)
→HTMLで変化後の見た目(イベント発火をきっかけに起こる一部見た目の変化)①何をきっかけに(イベント発火は何?)
きっかけはフォームの送信
「フォームのボタンを押した時」というのを記述。
###.js(JavaScriptファイル)$(function(){ $(*****).on(*****, function(){ }) })フォームに設定したのクラス名を $( )に入れて、
「.on」で押すという意味を加える。
「on( , 」のon( の後には何を押すのかをいれる。
今回は'submit'ボタンを入れた。<記述例>$(function(){ $('.js-form').on('submit', function(){ }) })また、console.logを用いてイベント発火しているか確認もしてみてください。
空いている行に記述して送信ボタンを押すことで確認できます。
<例>console.log("テスト")
などカッコに入れてみてください。
できていない時は検証のコンソールでエラーが出るはずです。
次に、デフォルト設定の方のフォーム送信を停止
今のままだとデフォルトの設定として、
フォーム送信と共に画面が今まで通り(非同期通信ではなく)画面遷移(画面移動)してしまう。
通常設定は阻止する必要がある。
非同期通信を行うために、preventDefault()を使用する。###.js(JavaScriptファイル)$(*****).on(*****, function(e){ e.preventDefault() }) })この際も真ん中の空いている行にconsole.logを入れてエラーが出てないか確認してみてください。
②イベントきっかけにどんなとこを実行するか
- Ajaxを使用(データ関連の引き渡し)
- HTMLで変化後の見た目(イベント発火をきっかけに起こる一部見た目の変化)
Ajaxを使用(データ関連の引き渡し)
この後必要になる基本のコード
先ほどのコードに 「$.ajax({」から追加しています。javascripts/###.js$(function(){ $(*****).on(*****, function(e){ e.preventDefault() // ここから下追加記述 $.ajax({ url: 取得したリクエストURL, //同期通信でいう『パス』 type: 'POST', //同期通信でいう『HTTPメソッド』 data: 取得したFormData, dataType: 'json', processData: false, contentType: false }) }) })↑この記述を行っても遷移先のviewファイル(〇〇.json.jbuilder)を作成していないとエラーが出ます。
ここからは送信フィームをイベントとした例を元にみていきます。
<例>$(function() { $('.js-form').on('submit', function(e) { e.preventDefault(); // ここから下追加記述 let formData = new FormData(this); let url = $(this).attr('action'); $.ajax({ url: url, type: "POST", data: formData, dataType: 'json', processData: false, contentType: false }) }); });
「フォームに入力された値を受け取れるようにする記述をする」
FormData
フォームのデータの送信に使用。
new FormData(フォーム要素)とすることでFormDataを作成。
今回の場合オブジェクトの引数はthis。
イベントで設定したfunction内でthisを利用した場合は、
イベントが発生したノード要素を指す。
今回の場合は、js-formというクラスがついたフォームの情報を取得している。
IDなどでも取得できる。<例>のFormDataについてlet formData = new FormData(this);
attrメソッド
引数に指定した属性の値を取得することができる。
<例>のattrメソッドとurlについてlet url = $(this).attr('action');例では引数に'action'を指定しているので(ここではthis)from要素のaction属性の値が取得できる。
「/songs/3/songcolors」このパスがactionから取れてurlに入れられてる。
そのurlがAjaxのurlに関わってくるのだと思います。
「$.ajax」の部分に非同期通信に必要なオプションを設定
<例>$.ajaxからの記述$.ajax({ url: url, type: "POST", data: formData, dataType: 'json', processData: false, contentType: false })
オプション 内容 type HTTP通信の種類を記述する。通信方法は、GETとPOSTの2種類。 url リクエストを送信する先のURLを記述する。遷移先、パス data サーバに送信する値を記述する。今回はデータを格納したものが入る。 dataType サーバから返されるデータの型を指定する。 processData デフォルトではtrue。dataに指定したオブジェクトをクエリ文字列(例: msg.txt?b1=%E3%81%8B&b2=%E3%81%8D )に変換する役割。 contentType サーバにデータのファイル形式を伝えるヘッダ。FormDataをつかってフォームの情報を取得した時には必ずfalseにする。さらに詳しくはこちら。
HTMLで変化後の見た目(イベント発火をきっかけに起こる一部見た目の変化)
非同期通信の結果(ブラウザの見た目としての変化)として返ってくるデータは、done(function(data) { 処理 })の関数の引数で受け取る。
doneメソッドを使う。また、doneメソッドで受け取った引数( )を元に「function buildHTML〜」の後からHTMLを組み立てる。
javascripts/###.js$(function(){ //ここから下5行追記 function buildHTML(***jsファイル名***){ let html = `<*******> </*******>`//`から`の間にHTMLが入る。 return html; } $(*****).on(*****, function(e){ e.preventDefault() let formData = new FormData(this); //フォームからデータをとってくる場合この一文を必要とする。 let url = $(this).attr('action'); //フォームのアクションに指定されたものが必要になる場合この一文が必要。 $.ajax({ url: 取得したリクエストURL, //同期通信でいう『パス』 type: 'POST', //同期通信でいう『HTTPメソッド』 data: 取得したFormData, dataType: 'json', processData: false, contentType: false }) //ここから以下追記 .done(function(data){ let html = buildHTML(data); $('.***ボタンのクラス***').prop('disabled', false) //一度押すと押せなくなる送信ボタンを連続で押せるようにしている $('***元のHTMLに追加したい場所を指定***').prepend(html);//.prepend指定した要素の最初に、引数で指定した内容を追加 }) }) })doneメソッド
.when( ) は先に実行したい処理。
.done( ) は後で実行したい処理。
のように処理をいつしたいか設定できます。
$('.ボタンのクラス').prop('disabled', false)
disabled属性をfalseにする記述でsubmitボタンが押せないのをfalseで解除する。
function buildHTMLL( ){let html = `<****></****>return html;}
doneメソッドで受け取った引数( )を元にHTMLを組み立てる。
HTMLの組み立てはつど全く違っているのでここに記述しておりませんが自分のコードを例に置いておいきます。<例>HTMLの箇所をピックアップしたものfunction buildHTML(songcolor){ let html = `<li class="color-box" style="background-color:${songcolor.color}"></li>` return html; };検証ツールで追加したいHTMLを見てみるととてもわかりやすいのと、
データベースの情報を表示する際は${}を使用すること、
ここに持ってくる情報は対応するviweに作った.json.jbuilderに設定したことを思い出すとわかりやすいかも。
prependメソッド
元のHTMLのどの部分に追加するのかクラスなどを指定して決める。
指定した要素(クラスなど)の最初に足すことができる。
そのほかにも最後に足したりするメソッドなども存在する。
このように様々なメソッドを使用することで、
テキストボックス内をイベント後に空にしたり設定することができる。
イベント発火により実行することが実装できたら…
その実行ができなかった場合を想定する
javascripts/###.js$(function(){ function buildHTML(******){ let html = `<*******> </*******>` return html; } $(*****).on(*****, function(e){ e.preventDefault() let formData = new FormData(this); let url = $(this).attr('action'); $.ajax({ url: 取得したリクエストURL, type: 'POST', data: FormData, dataType: 'json', processData: false, contentType: false }) .done(function(data){ let html = buildHTML(data); $('.******').prop('disabled', false) $('******').prepend(html); }) //ここから以下追記 .fail(function(){ alert('error'); }); }) })failメソッド
サーバーエラーの場合にdoneではなくfailが呼び出される。
alertメソッド
アラートが呼び出される。('****')の中身の文字がアラートで表示される。
以上です!
これで非同期通信の作業は最後です。
ほかにも様々な設定ができるのでこればかりではないのですが、
一旦ここで終わります。
最後にひとこと
ここまでまとめてみて、
一つ一つの記述の意味がより理解できました。
ただ、実際に新たに自分のオリジナルのアプリを開発したからというのも合わさって
今回の理解につながったのだと思います。新たな疑問点や課題
- 非同期通信をする際の手順を自分で思い出しながら実装できるかの不安
- doneメソッドの引数であるHTMLの組み立て
- done後の様々な記述
- Ajax後の設定が他で応用できるのか
- 非同期通信以外にJavaScriptでできることがあるがどんな仕組みなのか
理解が深まっていても実装で使用できるか
また、まだまだ理解が追いついていない部分を学習していきたいと思います。
初めてJSみた時はこんなの読めないと思っていましたが
今は少し見慣れてパーツごとに見れるようになったのが嬉しいです。
最後まで読んでくださってありがとうございました!
ではまた〜
- 投稿日:2020-10-17T16:48:41+09:00
電卓の作成
電卓を作成します
足し算と引き算と掛け算と割り算ができる電卓を作ります。
body要素にinput要素を2つ記述します。input要素に計算するときの数値を記入します。select要素を1つ記述しますが、ここで足し算をするか引き算をするかなどを選択します。button要素をクリックするとinput要素とselect要素で指定した内容で計算してくれます。button要素にはonclick属性を設定してクリックしたときにclicked( )関数が発火します。
<body> <input id="num1"> <select id="s1"> <option>+</option> <option>-</option> <option>×</option> <option>÷</option> </select> <input id="num2"> <span>=</span> <span id="total"></span><br> <p>※半角数字を入力してください</p> <button onclick="clicked()">計算する</button> </body>script要素ではグローバル変数にnum1,num2,s1,totalを定義します。
clicked関数の最初にグローバル変数それぞれにbody要素側で取得したい要素を設定します。num1とnum2は計算するときの数値。s1は足し算、引き算などの計算方法。totalは計算結果を表示します。
「let t = 0;」は関数内での計算結果を後で代入します。
num1,num2,s1は「document.getElementById("id名")」の最後に「.value」をつけていますが、input要素やselect要素で記入したり選択した内容を変数に代入することができます。parseInt( )メソッドは引数に指定した値を数値に変換することができます。先ほどのnum1やnum2が取得している値は文字列として数字が代入されているので、数値に変換します。この後計算するためです。
switch構文は引数に指定しているものの値が「case」後の値ごとに処理を分岐できる構文です。例えば、s1 = "+"のときは「t = num1 + num2; break;」を実行します。"+"のときは足し算、"-"のときは引き算をするように分岐しています。
最後に「total.textContent = t;」で計算後の値tをtextContentを使ってid要素totalを持つspan要素に出力しています。
<script> let num1, num2, s1, total; function clicked() { num1 = document.getElementById("num1").value; num2 = document.getElementById("num2").value; s1 = document.getElementById("s1").value; total = document.getElementById("total"); let t = 0; num1 = parseInt(num1); num2 = parseInt(num2); switch(s1) { case "+": t = num1 + num2; break; case "-": t = num1 - num2; break; case "×": t = num1 * num2; break; case "÷": t = num1 / num2; break; } total.textContent = t; } </script>以下のコードをコピーしてファイルに貼り付ければ試せます。select要素のoptionとswitch構文内のcaseを増やせばさらに計算方法を増やすこともできるので試してみてください。
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>calculater</title> <style> input { width: 100px; height: 30px; font-size: 25px; margin-right: 10px; } select { width: 50px; height: 30px; font-size: 25px; background-color: #eeeeee; margin-right: 10px; } span { width: 30px; height: 30px; font-size: 25px; margin-right: 10px; } </style> <script> let num1, num2, s1, total; function clicked() { num1 = document.getElementById("num1").value; num2 = document.getElementById("num2").value; s1 = document.getElementById("s1").value; total = document.getElementById("total"); let t = 0; num1 = parseInt(num1); num2 = parseInt(num2); switch(s1) { case "+": t = num1 + num2; break; case "-": t = num1 - num2; break; case "×": t = num1 * num2; break; case "÷": t = num1 / num2; break; } total.textContent = t; } </script> </head> <body> <input id="num1"> <select id="s1"> <option>+</option> <option>-</option> <option>×</option> <option>÷</option> </select> <input id="num2"> <span>=</span> <span id="total"></span><br> <p>※半角数字を入力してください</p> <button onclick="clicked()">計算する</button> </body> </html>
- 投稿日:2020-10-17T15:59:45+09:00
Java/JavaScript/C#で暗号化する
各言語で暗号化。
やってみると、暗号化後の文字列が各言語で違ってしまったりして、意外とハマったりします。
ここでは、Java/JavaScript/C#を取り上げてみます。暗号化
Java
まずは、Java。
Crypto.javaimport java.nio.charset.StandardCharsets; import javax.crypto.Cipher; import javax.crypto.spec.IvParameterSpec; import javax.crypto.spec.SecretKeySpec; import java.util.Base64; public final class Crypto { private static final String KEY = "1234567890abcdef"; private static final String IV = "abcdef1234567890"; private Crypto() { } private static Cipher createCipher(int mode) throws Exception { Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding"); SecretKeySpec key = new SecretKeySpec(KEY.getBytes(StandardCharsets.UTF_8), "AES"); IvParameterSpec iv = new IvParameterSpec(IV.getBytes(StandardCharsets.UTF_8)); cipher.init(mode, key, iv); return cipher; } public static String encrypt(String text) { try { Cipher cipher = createCipher(Cipher.ENCRYPT_MODE); Base64.Encoder encoder = Base64.getEncoder(); return encoder.encodeToString(cipher.doFinal(text.getBytes(StandardCharsets.UTF_8))); } catch (Exception e) { throw new RuntimeException(e); } } public static String decrypt(String text) { try { Cipher cipher = createCipher(Cipher.DECRYPT_MODE); Base64.Decoder decoder = Base64.getDecoder(); return new String(cipher.doFinal(decoder.decode(text))); } catch (Exception e) { throw new RuntimeException(e); } } }JavaScript
次にJavaScript。実行環境はNode.jsです。
Crypto.jsconst crypto = require('crypto') const KEY = '1234567890abcdef' const IV = 'abcdef1234567890' function createCipher(mode) { return crypto[mode]('aes-128-cbc', KEY, IV) } function encrypt(text) { const cipher = createCipher('createCipheriv') const encrypted = cipher.update(text); return Buffer.concat([encrypted, cipher.final()]).toString('base64') } function decrypt(text) { const buf = Buffer.from(text, 'base64') const cipher = createCipher('createDecipheriv') const decrypted = cipher.update(buf); return Buffer.concat([decrypted, cipher.final()]).toString('utf-8') }C#
最後にC#。
Crypto.csusing System; using System.Security.Cryptography; using System.Text; public sealed class Crypto { private const string KEY = "1234567890abcdef"; private const string IV = "abcdef1234567890"; private Crypto() { } private static AesManaged CreateAesManaged() { AesManaged aes = new AesManaged(); aes.KeySize = 256; aes.BlockSize = 128; aes.Mode = CipherMode.CBC; aes.IV = Encoding.UTF8.GetBytes(IV); aes.Key = Encoding.UTF8.GetBytes(KEY); aes.Padding = PaddingMode.PKCS7; return aes; } public static string Encrypt(string text) { AesManaged aes = CreateAesManaged(); byte[] byteText = Encoding.UTF8.GetBytes(text); byte[] encryptText = aes.CreateEncryptor().TransformFinalBlock(byteText, 0, byteText.Length); return Convert.ToBase64String(encryptText); } public static string Decrypt(string text) { AesManaged aes = CreateAesManaged(); byte[] src = System.Convert.FromBase64String(text); byte[] dest = aes.CreateDecryptor().TransformFinalBlock(src, 0, src.Length); return Encoding.UTF8.GetString(dest); } }結果
暗号化(
encrypt
)すると、以下の結果になります。
- ""(空文字)=> 0e8Yyuobp55/giEyC01lbg==
- alz1590-'$ => cMgaJ1X/cVENp+rnMo/8Kw==
- あむんアムンアムン亜無漚錡?? => jXw9bzISBZsndhcrJx/gJU7ltBzSp34xn6CL3xBbNE2yC0FhQBisP27WOXan/W2o
復号(
decrypt
)すると、元の文字列が得られます。補足
IV
は初期化ベクトルです。同じデータであっても違う暗号文にするための文字列です。KEY
/IV
は長さに決まりがあるので注意。
- 投稿日:2020-10-17T15:46:14+09:00
【React Native + Expo】React Hook Formでバリデーションを簡易実装してみる
React Hook Formはフォームバリデーションをシンプルかつ簡単に記述できる便利なライブラリです。
FormikやRedux Formなどバリデーションに関してのライブラリは他にもありますが、
パフォーマンスの良さや記述量の少なさからこちらのライブラリを使うと実装が楽になるのでオススメです。ReactNativeに関しては以下のURLにクイックスタートがかかれているので、参考にしてみてください。
https://react-hook-form.com/jp/get-started#ReactNativeReact Nativeの注意点
ReactNativeのサポートはしっかりとされていますので、使うことはできます。
ただし注意点としては、Reactと同様のAPIが使えない部分があるとのこと。React Native と互換性のない API がいくつかあります (Web とネイティブとの API の違い)。
また、書き方についても手動登録 (manual register)が必要とのこと。。。
とにかくソースコードを確認してみましょう。ソースコード
import { useForm, Controller } from 'react-hook-form';const { register, control, handleSubmit, errors } = useForm(); const onSubmit = (data) => console.log(data);<Controller control={control} render={({ onChange, onBlur, value }) => ( <TextInput onBlur={onBlur} onChangeText={value => onChange(value)} value={value} /> )} name="firstName" rules={{ required: "入力が必要です。" }} defaultValue="" /> {errors.firstName && <Text>{errors.firstName.message}</Text>}該当ソースコードは以上で、だいぶスッキリと書ける印象です。
補足
Controller
<Controller control={control} render={({ onChange, onBlur, value }) => ( <TextInput /> )} name="firstName" rules={{ required: "入力が必要です。" }} defaultValue="" />先程の「手動登録 (manual register)が必要」というのはController内にあるrulesにあたる箇所になります。
そもそも、registerとはバリデーションルールを設定するためのもので、useForm内でも定義することができます。errors
{errors.firstName && <Text>{errors.firstName.message}</Text>}バリデーションエラ-の内容はuseFormで定義されているerrorsを呼び出すことで確認できます。
上記のソースコードでのerrorの内容は、Controller内にあるrulesに定義した「入力が必要です。」が出力されます。実装例
— がーみ (@garmigarmi) October 17, 2020終わりに
今回紹介した内容は一部分だけですので、APIリファレンスを読んで書き換えたりすると理解が深まるかと思います。
また。実装で必要なバリデーションルールに沿ったものが、作れるのかを試してみようと思うので
詳細な作りに関してはまた別の記事で書こうかと思います。まだ、まとめきれていない部分が多々あるので、実装方法としてこうしたほうが良いとか間違いがあれば教えていただくと嬉しいです。
- 投稿日:2020-10-17T15:11:15+09:00
@vue/cliのインストールからVueプロジェクト作成まで
はじめに
今回は@vue/cliのインストールをしてから実際にVueプロジェクトを実行するまでを書いていきます!
Node.jsがインストールされている必要があるので、
まだインストールできていない人はNode.jsのインストール方法(Windows)を見てね!目次
- @vue/cliのインストール
- vue create コマンドでVueプロジェクトの作成
- 実際にブラウザで確認してみよう!
1. @vue/cliのインストール
- @vue/cliはVueプロジェクトの雛形を作るのを便利にしてくれるコマンドラインインタフェースです! 以下のコマンドを実行するとインストールできます!
$ npm install -g @vue/cli
- @vue/cliが正しくインストールされているかを確認する場合は「vue --version」を実行し、 バージョン情報が表示されればOK!
$ vue --version @vue/cli 4.5.72. vue create コマンドでVueプロジェクトの作成
- 「vue create project-name」を実行すると作成されます(project-nameは自分の好きな名前で作れます)
$ vue create sample
- 以下のように表示されたらエンターでOK!
- Vueプロジェクトの雛形が以下のように生成されます
3. 実際にブラウザで確認してみよう!
- 作成されたプロジェクトフォルダに移動し「npm run serve」を実行!
$ cd sample$ npm run serve
- ブラウザを開いて「http://localhost:8080」にアクセスし下図のような画面が表示されていれば成功!
- 投稿日:2020-10-17T14:22:53+09:00
【JS/GCS】ファイルアップロードオプション
内容
GCSに画像やら動画やらをアップロードする実装についてメモしておきます。
fs.createReadStream
下記のドキュメントで実装されています。
Cloud Storage の使用 | Node.js ドキュメントに対応した App Engine フレキシブル環境上記で実装している
blob.createWriteStream
メソッドの中身を見てみると以下のようなサンプル実装もあり、参考になります。import * as fs from 'fs' fs.createReadStream('panda.jpg') .pipe(file.createWriteStream({ metadata: { contentType: 'image/jpeg', metadata: { custom: 'metadata' } } })) .on('error', function(err) {}) .on('finish', function() { // The file upload is complete. });ファイル作成
また
createWriteStream
を使って、バイナリからファイルを作成することも可能です。const stream = fs.createWriteStream(filename); // 'image.png' とか 'video.mp4' とか stream.write(binary) // バイナリデータをファイルに書き出す
bucket.upload
下記の場合だとサーバー上に画像が吐き出される形になります。
const bucket = this.gcs.bucket('staging'); bucket.upload(filename, { // GCSのフォルダ構成を指定 // filenameは、'image.png' とか 'video.mp4' とか destination: `test/${filename}`, gzip: true, metadata: { cacheControl: 'no-cache', }, }).catch((err)=>{ console.error(`Failed to Upload`) });Google Cloud Storageにファイルを保存する - iyuichiの私的開発ログ
file.save
バイナリをそのままアップロードする方法です。
save
メソッドの引数がバイナリでも受け取ることができるので(any型)、ファイルをサーバー上に作成せずともGCSにアップロードすることが可能です。const bucket = this.gcs.bucket('staging'); // バケットの指定 const blob = bucket.file(`test/${filename}`); // ここでフォルダ構成 + ファイル名を指定できる return blob.save(binary) // バイナリデータを指定 .then(() => { return file.getSignedUrl({ // 必須項目は、action と expires action: 'read', expires: '03-09-2500', }) }) .then((urls: any[]) => { const url = urls[0]; return url }) // 特に expires とか設定しないのであれば、`https://storage.googleapis.com/staging/test/${filename}` とかで返すことも可能 .catch((err: any) => { console.log(`Unable to upload encoded file ${err}`) })参考にした記事
uploading buffer or string · Issue #2334 · googleapis/google-cloud-node · GitHub
File - Documentation
- 投稿日:2020-10-17T13:40:41+09:00
【React】 合成イベント(SyntheticEvent) を利用する時注意点
Reactの合成イベント(SyntheticEvent )特性
- ブラウザのイベントハンドラーとReactのSyntheticEvent は別である
- SyntheticEventはPullingされる。
- SyntheticEvent再使用される。
- 全ての属性は呼び出し後に初期化される。
実際にエラーを作てみましょう
export default function App() { const syntheticEvent = (event) => { // 1.全ての属性は呼び出し後に初期化される。 setTimeout(() => {. console.log(event.target.value); //2. 非同期でevent.target.valueを呼ぶと警告が発生する!! }, 1000); }; return ( <div className="App"> <input type="text" onChange={syntheticEvent} /> </div> ); }警告発生
Warning: This synthetic event is reused for performance reasons. If you're seeing this, you're accessing the property >
target
on a released/nullified synthetic event. This is set to null. If you must keep the original synthetic event >around, use event.persist(). See https://fb.me/react-event-pooling for more information.解決方法
1. event.persist()を追加する
export default function App() { const syntheticEvent = (event) => { event.persist() // 1. 警告が書いているメソッドを追加 setTimeout(() => { console.log(event.target.value); }, 1000); }; return ( <div className="App"> <input type="text" onChange={syntheticEvent} /> </div> ); }補足
非同期処理の中でイベントのプロパティにアクセスしたい場合は、event.persist() をイベント> 内で呼び出す必要があります。これにより、合成イベントがイベントプールの対象から除外され、イベントへの参照をコードで保持できるようになります。上のreactドキュメントはevent.persist()を利用する場合。
①. 合成イベントがイベントプールから除外される。
②. ①の理由で呼び出し後に初期化されない。
③. ②の理由で非同期の内部でもevet.target.valueの値が利用できるevent.persist()を利用する事は上の①の理由でオススメしない。
2. event.target.valueの値をPrimitive(プリミティブ)値で取得
export default function App() { const syntheticEvent = (event) => { const value = event.target.value // 1.primitive値で取得 setTimeout(() => { console.log(value); //2.警告は発生しない値を表示 }, 1000); }; return ( <div className="App"> <input type="text" onChange={syntheticEvent} /> </div> ); }この方法でする事をオススメします。
合成イヴェントを除外しなくても利用できます。結論
Reactの合成イベントを利用する時は非同期処理について注意が必要
setStateなども非同期で処理するので注意!参考記事
https://ja.reactjs.org/docs/events.html#gatsby-focus-wrapper
- 投稿日:2020-10-17T11:45:11+09:00
ディスプレイに描画できるようにする
ディスプレイに描画できるようにする
ディスプレイに文字を記述したり消したりできるようにします。
まず、body要素内にcanvas要素とbutton要素を記述します。
文字等はcanvas内に描画できるようにして、button要素をクリックすると描画したものを消去できるようにします。
canvas要素を取得できるようにcanvas要素内にid属性を設定します。
button要素をクリックしたら描画したものを消去するイベントを発火させるようにonclick属性を設定します。<body onload="init()"> <canvas id="canvas" width="700" height="700"></canvas><br> <button onclick="eraser()">消去</button> </body>グローバル変数に「ctx」と「points」を設定します。pointsは描画した軌跡のデータを全て記録できるように配列にします。
上記のbody要素にonload属性を設定しているので、ブラウザがページが読み込んだ後に「init( )」関数が発火します。
init( )関数内はまず、canvasに描画できるように変数canvasにbody内のcanvas要素を取得させ、変数ctxにコンテキストを取得させます。
次にキャンバスがマウス等で「押されたとき①」、「押された状態でマウスが動いたとき②」、「押していた状態から離されたとき③」でそれぞれ関数を設定します。①「onmousedown」プロパティを変数canvasに設定して、マウスが押されたときにmymousedown関数が発火します。mymousedown関数は押した時点のキャンバス内の座標を配列pointsに挿入します。
引数に「e」を指定することで押したときのいろいろな情報を取得できます。「e.offsetX」で押したときのキャンバス上のx座礁、「e.offsetY」で押したときのy座標を取得できるので、それぞれxとyの値とします。②「onmousemove」プロパティはマウスが動いたときにmymousemove関数が発火します。「if(points.length > 0)」とすることで、points内にデータが1つ以上無いとx,y座標データをpoints内に追加できないようになっています。つまりマウスが押されていないときはデータが追加できません。
pushメソッドは引数内の要素を指定した配列の末尾に追加するメソッドです。マウスが押された状態で動くたびにpointsの末尾に座標データが追加されます。
paint()関数でマウスが動いた軌跡を描画します。③「onmouseup」プロパティはマウスが押された状態から離されたときにmymouseup関数が発火します。pointsを空にすることで描画を中断します。
eraser( )関数は描画したものを消去することができます。「clearRect」メソッドは指定した要素を指定した範囲分消去することができるメソッドです。
paint( )関数はマウスを押下した状態で動かした軌跡を描画する関数です。「if(points.length <= 1) { return; }」で配列にデータが無いときは描画できないようにしています。
「ctx.beginPath( );」は描画を開始するときに用いるメソッドです。「moveTo( )」メソッドは描画するときの開始点となる座標を設定するメソッドです。moveTo(x, y)それぞれxがx座標、yがy座標。
「lineTo( )」メソッドは直前に指定した座標から直線を引く新たな座標を設定するメソッドです。lineTo(x, y)それぞれxがx座標、yがy座標です。このlineTo( )メソッドをfor文で繰り返すことでpoints内の軌跡データを繋ぐことができます。
「strokeStyle」プロパティは描画するときの色を指定できます。
「stroke( )」メソッドはctx.beginPath( );以降の座標を辿って、指定した色で実際に描画してくれます。<script> let ctx, points = []; function init() { let canvas = document.getElementById("canvas"); ctx = canvas.getContext("2d"); canvas.onmousedown = mymousedown; canvas.onmousemove = mymousemove; canvas.onmouseup = mymouseup; } function mymousedown(e) { points = [{ x: e.offsetX, y: e.offsetY }] } function mymousemove(e) { if(points.length > 0) { points.push({ x: e.offsetX, y: e.offsetY }) } paint(); } function mymouseup(e) { points = []; } function eraser() { ctx.clearRect(0, 0, 700, 700); } function paint() { if(points.length <= 1) { return; } ctx.beginPath(); ctx.moveTo(points[0].x, points[0].y); for(let i = 1; i < points.length; i++) { ctx.lineTo(points[i].x, points[i].y); } ctx.strokeStyle = "#333333"; ctx.stroke(); } </script>以下のコードをコピーしてファイルに貼り付けていただければ、試すことができます。
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>draw</title> <style> canvas { border: 1px solid black; } button { width: 100px; height: 30px; } </style> <script> let ctx, points = []; function init() { let canvas = document.getElementById("canvas"); ctx = canvas.getContext("2d"); canvas.onmousedown = mymousedown; canvas.onmousemove = mymousemove; canvas.onmouseup = mymouseup; } function mymousedown(e) { points = [{ x: e.offsetX, y: e.offsetY }] } function mymousemove(e) { if(points.length > 0) { points.push({ x: e.offsetX, y: e.offsetY }) } paint(); } function mymouseup(e) { points = []; } function eraser() { ctx.clearRect(0, 0, 700, 700); } function paint() { if(points.length <= 1) { return; } ctx.beginPath(); ctx.moveTo(points[0].x, points[0].y); for(let i = 1; i < points.length; i++) { ctx.lineTo(points[i].x, points[i].y); } ctx.strokeStyle = "#333333"; ctx.stroke(); } </script> </head> <body onload="init()"> <canvas id="canvas" width="700" height="700"></canvas><br> <button onclick="eraser()">消去</button> </body> </html>
- 投稿日:2020-10-17T03:01:48+09:00
javascriptを使用して、音声や音楽を流す方法
前置き
私は独学でプログラミング学習を始めて3か月の初学者です。
何度も壁にぶつかりながら、学習を進めていく中で、先駆者の方々の記事に助けられてきました。
私も悩んでいる方の助けになればと思い、記事を投稿することにしました。この記事はWebアプリの制作過程で、Javascript(以後JSと略称を使用します)のイベント時や特定の処理を実施した際に、音声を再生したいという思いから調べた内容がもとになっています。
もともとHTMLにはaudio要素があり、audio要素のsrc属性にファイルの場所を指定して利用することで音声を再生できます。
しかし、Railsの環境下だとファイル場所の指定がうまくいかず、つまずいた結果、『audiojs-rails』というGemを使用することにしました。目的
この記事では、『再生プレイヤーを非表示にして、HTMLのInputボタンを押した際に音声を再生する』ということを目的として記載していきます。アレンジを行えば、特定の処理が終わった後に再生をするということが可能になります。
使用環境
OS:Win10
Rails 5.2.4.4
Ruby 2.6.6
現在はローカル環境で開発中目次
◆Gemのインストールと使用方法
◆特定のイベントによって再生ができるようにアレンジ
◆再生プレイヤーを非表示に!◆使用するGemのインストールと使用方法
1.Gemfileに下記の内容を追加してbundle installを行います。
※rails serverを起動している場合は再起動してください。
gem 'audiojs-rails'2.audiojsの初期化と再生プレイヤー設置
音声データを再生したいViewに下記の内容を記載します。
audiojs.createAll()によって再生プレイヤーが作成されます。
※再生プレイヤーはいらないよ!って方でも、再生できるか確かめるために下記の内容をViewへ記載することをお勧めします
※sample.mp3は、ご自分が用意した音源ファイルの名前に変更してください。<!-- 再生プレイヤー --> <%= audio_tag 'sample.mp3' %> <!-- audiojsの初期化 --> <script> const audioPlayer = audiojs.createAll(); </script>3.assetsパスの追加
上記で設置した再生プレイヤーで読み込んでいる『sample.mp3』は音声ファイルの名前です。
お好きなファイルを用意していただければよいのですが、保存場所には注意が必要です。
必ず、app/assets/audios/に配置するようにしましょう。(私はaudiosのフォルダがなかったので作成しましたが正常に動作しました。)しかし、保存しただけでは使用できませんので、アセットパイプラインで配信するために、assetsパスを追加します。
config/initializers/assets.rb に下記を追加します。config/initializers/assets.rbRails.application.config.assets.paths << Rails.root.join("app", "assets", "audios")4.assetsパスが追加されたか確認する。
皆さんが使用しているコマンドラインで、Rails consoleを起動して下記の内容を打ち込んでください。
Rails.application.config.assets.paths結果として、末尾にaudiosと書かれたフォルダパスが読み込まれていれば問題なさそうです。
※下記のフォルダパスは一例なので、皆さんがWebアプリを保存している場所によって変わります。"C:/Users/sample/ruby/webapp/app/assets/audios"パスが追加されたことを確認したら、再生できるか試してみましょう。
再生ができたら、準備満タンです。◆特定のイベントによって再生ができるようにアレンジをする。
1、ViewにInputタグを追加してIDを設定し、それをScriptで読み込む。
今回は、operationというIDを振って変数に代入しています。
<input type="submit" id="operation"> <script> const operation = document.getElementById("operation"); const audioPlayer = audiojs.createAll(); </script>2.再生プレイヤーの情報をaudio変数に代入して、inputをクリックしたときに、音声の再生を行う。
※必ず、audioPlayerのインデックス番号 [0] を入れた変数を用意してください。
audioPlayer.play();と入力しても動作しません。<input type="submit" id="operation"> <script> const operation = document.getElementById("operation"); const audioPlayer = audiojs.createAll(); # ここから追加した内容 const audio = audioPlayer[0]; operation.addEventListener("click", () => { audio.play(); }); # ここまで </script>なぜ audio に対して audioPlayer[0] を入れなければいけないのかは厳密には理解できていませんが、
audioPlayerの中身をConsole.logで覗いてみると下記のようになっていることがわかりました。
再生プレイヤーを生成したときの情報がaudioPlayerに入っています。
故にインデックス番号0の中身に音声ファイルの情報や、再生や停止といった操作にかかわる情報が入っているため、それを指定しないと動作しないのではないかと推測しています。◆再生プレイヤーを非表示に!
あとは簡単、Audio_tagをDivタグで囲ってあげて、CSSのDisplayをnoneにしてあげるだけです。
<div class="none"> <%= audio_tag 'decision48.mp3' %> </div>最後に
今回いろんな記事の情報を自分なりに操作した内容をまとめてみました。
何かお気づきな点ございましたら、お教えていただけると助かります。
参考にさせていただいた記事もまとめておきますので、ご興味のある方は是非!・【Rails】audiojs-railsの導入からオーディオファイル再生までの手順
↑再生プレイヤーのオプションもまとめられています。再生プレイヤーをいじりたい人は是非。
・MP3を再生するjavascript(audio.js)のメモ
↑jQueryを使用して、再生ボタンや停止ボタンを作っています。応用すればJSだけでも同じことができるかもしれません。
- 投稿日:2020-10-17T01:17:41+09:00
Handsontableのレンダラーまとめ
レンダラーとは
表示やトリガー(クライアント側からの操作に対してのイベント発火)など、セルの出力を制御する設定。
ハンズオンテーブルにはデフォルトで10個の設定がされている。
以下は公式からの抜粋
- autocomplete for Handsontable.renderers.AutocompleteRenderer
- base for Handsontable.renderers.BaseRenderer
- checkbox for Handsontable.renderers.CheckboxRenderer
- date for Handsontable.renderers.DateRenderer
- dropdown for Handsontable.renderers.DropdownRenderer
- html for Handsontable.renderers.HtmlRenderer
- numeric for Handsontable.renderers.NumericRenderer
- password for Handsontable.renderers.PasswordRenderer
- text for Handsontable.renderers.TextRenderer
- time for Handsontable.renderers.TimeRenderer
レンダラーの使用方法
See the Pen pobyPPg by mogumogu mogumi (@mgmgmogumi) on CodePen.
カスタムレンダラーとは
自分でレンダラーの設定をしたもの。
Tutorial: Custom renderers - Handsontable Documentationカスタムレンダラーの使用方法
デフォルトで用意されているレンダラー以外に、自分で設定することができる。
ちなみにデフォルトと同じ名前で設定すると、設定を上書きできる。
Handsontable.renderers.registerRenderer(rendererName, renderer)
関数を使用して設定する。参考
Handsontable 使い方メモ1(基本) - Qiita
おしまい