20200227のJavaScriptに関する記事は28件です。

【Ruby on Rails 5】Instagram風簡易SNSアプリを作ってみよう!(Techpit教材)を終えて

Techpitの【Ruby on Rails 5】教材の感想

TechCommitさんのお年玉企画にて頂いたTechpit教材を使って、Ruby on Rails 5で簡易アプリを作成しました。
簡単ではありますが、どのようなことを学べたのか、その感想を記します。

また、当方実務経験などが全く無く、言語を独学で学んでいる程度なので、経験も知識も非常に浅いことをご了承願います。

教材に取り組む上で必要な知識

まず、【Ruby on Rails 5】instagram風簡易SNSアプリを作ってみよう!という教材は、以下の言語を使用します

  • HTML
  • CSS
  • Javascript
  • Ruby

必要条件はHTML/CSS、及びRubyの基礎知識とされています。

主な目的はRuby on Railsの流れを把握するものであり、
SNSのinstagramを参考にしたアプリ作成を進める内容となっています。

今回の教材に取り掛かるにあたって、HTMLとCSS、Rubyの基礎知識をProgateで補っています。
教材は、2回ほど繰り返し学習を行いました。

※教材内でHTML/CSSは多く使われますが、詳しい解説はありません。

教材の流れと大まかな内容

  • 環境構築
    • Mac -Homebrew
    • Windows -Cloud9
  • Railsアプリケーション作成
    • Gemインストール
    • ローカルサーバー立ち上げ
  • MVC知識
  • Bootstrap導入
  • 機能を付ける
    • サインアップ・サインイン
    • プロフィール
    • 画像投稿
    • いいね
    • コメント
  • デプロイ
    • Herokuを利用してサービス公開
  • pry-railsを用いたデバック方法

どのファイルでどのコードを記述するか、コードの意味から、詳しい情報が書いてある詳細ページのリンクも要所要所あります。

また、各項ごとに質問投稿欄があり、わからないことが運営へ質問出来るようになっていました。

全体を通しての感想

プログラミング超初心者ながら教材を終えて、感想を大きく三つあります。

  • 初心者にも作れるわかりやすさ
  • 使用する知識が多い
  • エラーに慣れてくる

初心者にも作れるわかりやすさ

アプリを作るというと難しそうだなとは思っていましたが、
一つ一つのページを作り、それを組み立てるような流れでわかりやすかったので、
進めていければアプリ作成・公開まで行うことが出来ます。

使用する知識が多い

教材内容全てを理解する、というのは、特に言語など基礎の基礎を学んだだけでは出来ませんでした。使用する言語も多い(ように感じた)ので、基礎知識しか無い段階で全て理解しようとすると相当な時間がかかると思われます。

といっても、そもそもこの教材の一番目的がRuby on Railsの流れを把握することなので、まずは流すように取り組むだけでも、大枠が見えてきます。
細かいことを知りたい時はそのページで質問するでも、リンクを参考にするでも可能なところが良かったです。

エラーに慣れてくる

私が初心者なせいかとは思いますが、教材通りにしているつもりでもどこかしらでエラーが起きて躓いてしまうことが多々ありました。

しかし自分が躓いていることは大体他の人も躓いていることが多かったので、特に各項の質問投稿欄は、同じエラーで解決した人が居たりして、非常に助けになり、また、何度かエラーを繰り返すことでエラーの直し方や着目すべきところも以前より見えるようになった気がします。

まとめ

長くなりましたが、この教材の対象者でもあるように、Ruby on Rails開発の流れをつかみたい人、アプリを作成してみたい人、特にRubyを学んでいる方にはおすすめです。

しかし感想でも触れましたが、やはり言語の面での自分の知識不足が痛かったです。
基礎知識をしっかり固めてやると、もっと入りやすいのかなと思いました。教材としては扱いやすくてとても良かったです。

アプリ作成、そしてサイトの公開まで学べるという点で、知識の色んな活用の仕方が出来るのではと思います。

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

リダイレクトFizzBuzz

結果表示

capture1

計算過程

capture2

リポジトリ

matoruru/redirect-fizzbuzz - GitHub

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

文系ガチの未経験だった僕が自力4ヶ月弱で自社開発のweb系会社で新卒内定をもらうために行ったこと

誰に読んで欲しいか

・文系新卒未経験の方
・web系の会社で働きたい方
・フリーランスでアソビタィ!!

偉そうに書きますがご容赦ください><

なぜ書くのか

実際に自分がエンジニアになりたいと思った時に情報が全くなかったから。
何をしなければいけないかが全くわからなかった。

web系で就職した人や未経験理系卒の方の情報は多少あれど文系未経験新卒でweb系エンジニアになった人の情報は全くなかったため。しかし文系卒のエンジニア志望は増えて来ていてニーズはかなりあると考えた。

自己紹介

早稲田大学文系3年生。
長所は考えた上で実際に行動にすぐに移せること。
大学生時代は酒飲み、遊び、そしてオーストラリアとニュージーランドでワーキングホリデーを行い、ガチガチの現地の環境に身を置いて生活をした。
その時に初めてテクノロジーに触れて衝撃を受け、ITに興味を少し持つ。
ものを作ってびっくりさせることが好き。

自分が行ったこと

3年生の夏

コンサル目指してサマーインターンを応募しまくるも落選落選。
→自己分析を重ねてどう考えても仕事よりノマドになって海外で自由に働きたいと強い決意。

10月前半

・週3働いていたマーケのインターンを辞め、飲み会などを減らし、未来への投資として勉強する。
実際にprogateという初心者向けの学習サイトで月額1000円払ってHTML,CSSを2週ほどした。
 →一周2日あれば余裕
 →月額1000円はスクールと比較すればどう考えても格安
・その後実際に自分の作ってみたいサイトを5つほどアウトプットしてみる
・その後同じものでJavaScriptを学び、難しかったので5週ほどした。

10月後半

・インターンを視野にいれて重役のいる大手コンサルでの長期インターンの条件としてあげられた制作物の作成に励む。
 ・課題の内容としてはとあるチャットアプリのAPIを使ったアプリ内メッセージ検索webアプリ
 ・AWSを使ったデプロイまで行うよう指示される
 ・文系なのでエンジニアの友人もいなかったため小学校の時の友人、MatcherというOB訪問アプリで 出会った社会人の方、前職場のエンジニアの方に再コンタクト
 ・正直かなり大変でエラー1つに数日かけることもしばしば
・Vue.jsというjavascript(js)の指定が確かあったため、Udemyというオンライン学習用動画を販売するサイトを利用し、1000円で購入し、課題と同時並行で勉強した。

11月後半

課題完成し、OKが出たが人数の関係で引き伸ばされた。
→しょぼいですがもしお時間あれば見てみてください..まだまだ改良中なのでお手柔らかに..
slackのメッセージ検索アプリ

早く実務経験を積みたかったため、諦めて自分でインターンを探し始める。
この時使ったものはMatcher,キャリアバイト,Infraというサービスたち。
まずエンジニアとしての働き方などベースを知るためにMatcherで20人ほど文系未経験卒のエンジニアの方中心に話を聞いた。

12月

その後早速実務未経験でも働けそうなインターンに応募。面接させてくれた企業は3つ。
1つ目の企業には面接中に断られる。

ここでフィードバックをお願いして教えてもらったこと
・普通に企業の目線で考えるとエンジニアを雇う意味は2つ。
 ❶即戦力で企業に利益をもたらすため
 ❷就職するかもしれないため将来を見越した研修込みの投資として

今このページを読んでいる人はおそらく❷を狙うしかない。
だから自分はそれ以降就職してもいい会社しか応募せず、面接も本気で就活のレベルで受けた。

12月後半

ゲームメディアを運営する企業で採用された。フロントでの努力を評価されバックエンドのPHPを使ったエンジニアとして研修込みでの採用。
同時にレバテックという人材サービスを利用し就活を視野に入れて自己分析をもっと極める。

1月

長期インターン開始。
後半からは面接も平日夜に毎日受ける。
→フィードバックを最大限に生かしてPDCA回して面接の受けが良くなっていく。

2月

ついに複数の企業から内定をいただく。
現在まだ一応他の企業も見ている。

すいません。日記のような形になりました。

まとめ

就職までの時間を考えて何をすべきか逆算していくことが大事。
正直自分は実務経験ないと就職できないと思ってインターンを必死に探したが、しなくてももしかしたらよかったかもしれない。
しかしインターンをして就活しながらも現在進行形で技術に触れていることをアピールできたのは大きかった所感。

インターンを受けるにあたって大事なことは
ちゃんと就職してもいい企業で受けると互いに良くて面接ももちろん通る。

就活では
・しっかりエンジニアになりたい理由を固めることは大前提必要。

・その上でそのために実際にこんなもの作って、インターンもやっている(何かしら活動している)から私はこれからももちろんエンジニアでゴリゴリ開発していきますよ?だって書くの好きだもん!ということを伝えることが絶対に必要。

おそらく面接官が心配していることは、
❶エンジニアなりたいのはわかったけど続けれるのか。文系やめる人多いけど。
❷成長は早くて遅い経験有りのエンジニアを雇うよりも将来的に利益になるのか。

ということ。
あとは文系ならでは(?)のコミュニケーション能力を面接で抜群に発揮して内定をもぎ取りましょう!!

感想

初めてのqiita投稿でした。
ずっと前から自分が情報なくて困っていたのでこういったことを内定もらったらすぐにしたいと考えていて、それが実行できたので嬉しいです。

次回は初心者から見た簡単なIT業界やエンジニアの中の詳しい職種の特徴を発信したいと思います。
もちろんコーディングの知識もアウトプットしたいと考えてます。

お手柔らかに、意見やコメントもらえると嬉しいです!
ありがとうございました。

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

無名関数とはなんぞや

そもそも関数とは

プログラム上での処理を1つのブロックにまとめたもの。
例えば引数として受け取った数値を二乗して返す関数があれば、関数の呼び出し元には戻り値として引数を二乗した値が帰ってくるわけです!javascriptでは以下のように書きます。「nijo」が関数になるわけですね。

result = nijo(2) //関数を呼び出して返り値をresultに代入

function nijo(i){
  //処理内容は中略
}

無名関数

上記を踏まえた上で、無名関数について解説します。簡単に言えば名前を決めずに定義できる関数です。

function(){
  //処理内容は中略  
}

先ほど記載した引数を二乗する関数には、関数名として「nijo」という名前がついていました。
しかし名前を決めずに関数を定義することもできるのです。

無名関数を使うことによるメリット

setTimeout関数を例にして、無名関数を使うメリットを見ていきましょう。
ちなみにsetTimeout関数の仕様は以下の通りです。
setTimeout(処理内容,実行タイミング)

setTimeout(function(){
  var day = new Date();
  alert("今日は" + day + "です");
}, 2000)

この処理をHTMLに埋め込んでブラウザで開けば、2秒後に今日の日付が表示されるわけです。
引数の処理内容の部分に無名関数を使っていますね!
処理内容として渡される関数1についてはここでしか呼ばれることがありません。
なので、関数に名前をつける必要がないのです!
ちょっと回りくどくなりましたが、以下のようなメリットがあります。
・関数名を決めなくてもいい処理の場合、関数の名前を考える手間を省ける。
・他の関数と名前が被ることが絶対にないので、予期せぬ動作やエラーの対応をしなくてもいい。

まとめ

無名関数を使いこなして効率的なコーディングを行いましょう!


  1. これをコールバック関数といいます。 

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

JavaScript Hoisting メモ

Hoistingとは

JavaScriptは変数宣言は必要がありません、自動的に変数名を設定されます。

example1.js
var a = 12;
console.log(a);//12

a = 12;
console.log(a);//12

example2は同じ結果になります。こられはhoistingということです。

example2.js
var a;
a = 12;
console.log(a);//12

a = 12;
console.log(a)//12
var a;

example3は無名と名つけ関数のHoistingの事例です。

example3.js
function a(x,y){
  return x+y;
}
console.log(a(x,y));//5

var b = function (x,y){
  return x+y;
}

console.log(b(2,3));//5


c = function (x,y){
  return b+c;
}

console.log(c(2,3));//5
var c;

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

JavaScriptで外部ファイルを動的に読み込む

やったこと

JavaScriptで外部ファイルを動的に読み込みました。

var script = document.createElement('script');
script.src = "%外部ファイルのパス%";
document.head.appendChild(script);

わかったこと

パッケージ製品やフレームワークの制約で、HTMLのscript属性が設定できない場合、JavaScriptから動的に読み込むことができる。

つぎにやること

読み込んだ外部ファイルのモジュールを使用する。

メリット

クライアントサイドで実現できる範囲が広がる。

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

IM-BISのクライアントサイドスクリプトAPIで現在の日付を設定する

やったこと

IM-BISのクライアントサイドスクリプトAPIで、現在の日付を設定しました。
参考:クライアントサイドスクリプトAPI

var args = {};
args.data = {};
args.data.%フィールド識別ID% = new Date();
formaItems.product_72_calendar.setItemData.%フィールド識別ID%(args);

わかったこと

IM-BISのクライアントサイドスクリプトAPIを使用することで、IM-FormaDesignerの日付やユーザ選択、組織選択など複数の値を保持するアイテム項目に安心して値を設定することができる。

つぎにやること

初期表示イベントやアイテムイベントで使用する。

メリット

画面上にある入力値を他の項目にコピーしたり、削除したりできる。

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

IM-BISのクライアントサイドスクリプトAPIでテキストボックスの値を取得する

やったこと

IM-BISのクライアントサイドスクリプトAPIで、テキストボックスの値を取得しました。
参考:クライアントサイドスクリプトAPI

var result = formaItems.product_72_textbox.getItemData.%フィールド識別ID%();
alert(result);

わかったこと

IM-BISのクライアントサイドスクリプトAPIを使用することで、IM-FormaDesignerで配置したアイテム項目の値をDOMを使用せずに取得することができる。

つぎにやること

IM-BISのクライアントサイドスクリプトAPIを使用して値を設定してみる。

メリット

名称とコードなど複数の値を保持するアイテム項目を簡単に設定できる。

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

JavaScriptで親画面の値を取得する

やったこと

JavaScriptで親画面の値を取得しました。

window.opener.document.getElementsByName("item01")[0].value;

わかったこと

window.openで開いた子画面から、window.openerを使用することで、親画面の値を取得することができる。

つぎにやること

window.openで開いた子画面から、親画面の値を設定してみる。

メリット

window.openで開いた子画面から、親画面を制御できる。

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

JavaScriptで日付を加算する

やったこと

JavaScriptで日付を加算しました。

var date = new Date();
date.setDate(date.getDate() + 1);

わかったこと

Date型オブジェクトのgetDateメソッドで値を取得し、加算した値をsetDateメソッドで設定することで、日付を加算することができる。

つぎにやること

年や月の加算もやってみる

メリット

様々な日付の処理に対応できる

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

続編:Javascriptでテキストを自動で円形にする

はじめに

この記事は別記事「HTMLとCSSで魔法陣を描いてみる」の続編です。続編みたいなものです。

自動化したので、長いテキストでも円形にできるようになった。

サンプル

See the Pen OJVmLOd by Yomogenium (@yomogenium) on CodePen.

コード

html
<style>
/* cssはなくても大丈夫だが、つけないとほぼ確実に見た目が悪くなる。 */
#test{
  background-color: black;
  color: white;
  position: relative;
  width: 400px;
  height: 400px;
}
</style>

<div id="test">I am the flesh and bone of my own sword, Steel flows through my body, And fire is what courses through my blood, I have created over thousand blades. Unknown to Death. Nor known to life, Many times have withstood enormous pain to create thousands of weapons. And yet those hands that are brave so much never hold anything, So as I pray now I call for “Unlimited blade works”.</div>

<script type="text/javascript">
(function(){

function ToArch(element){


  // 要素内のテキストを抜き出して配列にする
  var text = element.textContent;
  text = text.split('');

  // 要素内のテキストを1文字ずつかこみ、それらに角度と高さを設定
  element.innerHTML = '';
  for(var int = 0; int < text.length; int++){

    var divnode = null;

    // 要素の角度
    var divrotate = (360 / text.length) * int;

    divnode = document.createElement('span');
    divnode.innerHTML = text[int];
    divnode.style.position = 'absolute';
    divnode.style.height = '50%';
    divnode.style.color = 'unset';
    divnode.style.transformOrigin = 'bottom center';
    divnode.style.top = '0';
    divnode.style.bottom = '0';
    divnode.style.left = '49.5%';
    divnode.style.transform = 'rotate(' + divrotate + 'deg)';
    element.appendChild(divnode);
  }
  return element;
}

// 引数にはdocument要素を入れること。
var archtarget = document.getElementById('test');
ToArch(archtarget);
})();
</script>

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

TTCアルゴリズムで看護師のアサインメント表を自動作成1

2018年に院内で発表した内容です。
うちで商品化に至らなかったので、技術を放流します。
何話か続きます。通勤の合間に書いてます。

はじめに

マッチングアプリ、まだまだ流行ってますよね。その人が持っている要素と相性の良い人を何らかのアルゴリズムで結びつけるものです。

ナースのスケジューリング問題、ソフトウェア開発が盛んですよね。シフト表づくりの強い味方です。

この2つを合体させると、面白そうですよね。

あんまり世の中に無いのが、看護師は今日、どの入院患者を受け持ったら良いのかを決めてくれるソフトウェアです。

次の日の受け持ちを決めるの、時間かかるんですよ。あの看護師は新人で手術患者はまだ受けもてないとか、この患者は男性看護師不可とか、条件がいっぱいあるんです。

この受け持ち表を看護師アサインメント表と、うちでは呼んでいます。

入院患者は全員、看護師によって受け持たれないといけませんから、DAアルゴリズムだと、患者が看護師に対してdeferred acceptanceではたまったものではないので、TTCアルゴリズムにしようと思ったわけです。

というわけで、何話か続きます。

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

【JavaScript】Arrayの反復メソッドまとめ(forEach, filter, mapとか)

JavaScriptで使用できるArrayの反復メソッドについてまとめてみた

反復メソッドについて

  • これらのメソッドは配列を処理する際にコールバックされる関数を引数に取る。
  • メソッドが呼ばれたタイミングで配列のlength値を一時的に保存して処理を行うため、処理中に追記された要素は処理に影響を与えない
  • しかし、配列に対するその他の変更(要素の値の書き換えや削除)は、その要素が変更された後に処理中で参照する場合に操作に影響を与える。つまり、処理中に変更した要素を再度同じ処理中に参照しようとした場合、変更後の要素を参照することになる。

引数の説明

  • element: 配列内の要素を一つ一つ取り出したもの
  • index: 何回目のループかを検知するための番号
  • array: 元の配列

forEach

const list = [0, 1, 2, 3]
list.forEach((element, index, array) => {
  console.log(element)
})

// 0, 1, 2, 3
  • 配列の一つ一つをitemとして取り出して何かしらの処理を行うことができる

filter

const list = [0, 1, 2, 3]
const newList = list.filter((element, index, array) => {
  return (element > 1)
})

console.log(newList)

// [2, 3]
  • 元の配列から条件に当てはまるものだけを取得して、新しい配列を作成することができる
  • 条件に当てはまる要素だけで配列を作成したい場合や、要素の中の不要な要素を削除したい場合に活用できる

map

const list = [0, 1, 2, 3]
const newList = list.map((element, index, array) => {
  return element + 1
})

console.log(newList)

// [1, 2, 3, 4]
  • 元の配列から、何かしらの処理を加えて新しい配列を作成することができる
  • filterとの違いは、elementに整形処理や値を変更する処理を加えるかどうか
  • 新しく作成された配列を必ず使用することを目的としているため、処理だけを行いたい場合は、forEachなどを使用しなければならない

reduce, reduceRight

const list = [0, 1, 2, 3]
const totalVaule = list.reduce((previousValue, currentValue, index, array) => {
  return previousValue + currentValue
})

console.log(totalValue)

// 6
  • 配列の先頭から順番に処理を行う
  • reduceRightの場合は最後から順番に処理を行う

every

const list = [0, 1, 2, 3]
const isPassed = list.every((element, index, array) => {
  return element > 1
})

console.log(isPassed)

//false
  • 配列内の全ての要素がその条件に当てはまるかどうかを調べることができる

some

const list = [0, 1, 2, 3]
const isExist = list.some((element, index, array) => {
  return element = 3
})

console.log(isExist)

// true
  • 条件を満たすものがあるかを判定する
  • 処理中にtrueが返ってきたタイミングで処理が止まる

find

const list = [0, 1, 2, 3]
const target = list.find((element, index, array) => {
  element >= 2
})

console.log(target)

// 2
  • 条件に当てはまる配列内の最初の要素を返す
    • 要素が見つからない場合はundefinedを返す
  • 条件に当てはまる最初の添字が必要な場合は、findIndex()を使用する
    • 要素が見つからない場合は-1を返す
  • 配列内に要素が存在するかを調べる場合はincludes()を使用する

参考

Array MDN web docs

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

pug(2.0.0-beta11)でHTMLをエスケープさせずに出力する方法

pugでHTMLを記述した変数をエスケープさせずに展開させようとした際、

!{ 変数名 }

といった形で展開できると色んな記事で書いてあったのですが、私の環境では以下のようなエラーが出てしまいました。

/src/views/XXXX.pug nn| ~~~~ !{ 変数名 } ----------------------------^ nn| unexpected text "!{ 変数名"

結果的に以下の記述でHTMLをエスケープさせずにそのまま出力できました。

!= 変数名

どなたかの救いになれたら幸いです。

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

【JavaScript】Mapを正しく使うためにまとめた情報

はじめに

本記事は筆者がMapを使うために必要だと思った情報をまとめたものです。

Mapが実装されるまではJavaScriptに連想配列が存在せず、代わりにObjectで対応していたケースが多いようです。
ですので、Objectと比較した内容をメインに記載していきます。

Mapとの比較が分かりやすいように、ObjectのPropertyはkeyとして扱っています。

連想配列に関わる処理をObjectからMapにする事で得られるメリット

  • Objectと違い、StringとSymbol以外の任意の値もkeyに設定できる
  • 要素数の取得や反復処理が比較的容易(最初からメソッドが用意されている)
  • 頻繁に要素を追加・削除する場合、Objectよりもパフォーマンスが優れるケースがある
  • prototypeが無い為、余計なデータが存在しない

参考: MDN - Map - オブジェクトとマップの比較

メソッド・実装方法

ObjectとMapのメソッド・実装対応表

Objectで実装していた事をMapではどのようにすればよいのかをまとめました。

次の様にMapをmap変数、Objectをobj変数にセットした前提で記載しています。

let obj = {};
let map = new Map();
目的 Object Map
データのクリアー obj = {} map.clear()
データのセット obj[key] = value
obj.key = value
map.set(key, value)
keyによるデータの取得 obj[key]
obj.key
map.get(key)
keyによるデータの存在確認 key in obj map.has(key)
keyによるデータの削除 delete obj[key] map.delete(key)
要素数の取得 Object.keys(obj).length map.size
全ての[key, value]を格納した配列の取得 Object.entries(obj) Array.from(map.entries())
全てのkeyを格納した配列の取得 Object.keys(obj) Array.from(map.keys())
全てのvalueを格納した配列の取得 Object.values(obj) Array.from(map.values())

その他のMapのメソッド

for...ofでは必須のメソッドです。

目的 Map
全ての[key, value]の配列を含むIteratorの取得 map.entries()
全てのkeyの配列を含むIteratorの取得 map.keys()
全てのvalueの配列を含むIteratorの取得 map.values()

反復処理

本記事で記載はしていますが、for...infor...ofはESLintから怒られるので使わない方が良いかもしれません。
なるべくforEachを使用した方が良いかもしれません。
詳しくはAirbnb JavaScriptスタイルガイド - Iterators and Generatorsが参考になりますので、ご覧ください。

Map

for...inは使用できない(for...inはObjectのプロパティに対して反復処理を行うものの為)

forEach

forEach内の関数の引数の順番に注意。

// 動作確認用のデータ作成
const map = new Map();
map.set(1, 100);
map.set(2, 200);

// keyとvalueを取得
map.forEach((value, key) => console.log(`key = ${key}, value = ${value}`));

for...of

// 動作確認用のデータ作成
const map = new Map();
map.set(1, 100);
map.set(2, 200);

// keyとvalueを取得
for (const [key, value] of map.entries()) {
  console.log(`key = ${key}, value = ${value}`);
}

// keyを取得
for (const key of map.keys()) {
  console.log(`key = ${key}`);
}

// valueを取得
for (const value of map.values()) {
  console.log(`value = ${value}`);
}

Object

参考までにObjectについても記載。

for...ofは使用できない(Objectがiterableでない為)

Objectでfor...in以外を使った反復処理を行う場合は、Object.entries(obj)等で配列に変換してmapforEachを使用する。

map

// 動作確認用のデータ作成
const obj = {
  '1': 100,
  '2': 200,
};

// keyとvalueを取得
Object.entries(obj).map((item, index) => console.log(`index = ${index}, key = ${item[0]}, value = ${item[1]}`));

// keyを取得
Object.keys(obj).map((key, index) => console.log(`index = ${index}, key = ${key}`));

// valueを取得
Object.values(obj).map((value, index) => console.log(`index = ${index}, value = ${value}`));

forEach

// 動作確認用のデータ作成
const obj = {
  '1': 100,
  '2': 200,
};

// keyとvalueを取得
// Object.entries(obj)で返ってくる値は[ [ '1', 100 ], [ '2', 200 ] ]
// indexが配列のインデックス、itemに配列内の値(今回だと最初が[ '1', 100 ])が格納される。
Object.entries(obj).forEach((item, index) => console.log(`index = ${index}, key = ${item[0]}, value = ${item[1]}`));

// forEachでkeyを取得
Object.keys(obj).forEach((key, index) => console.log(`index = ${index}, key = ${key}`));

// forEachでkeyを取得
Object.values(obj).forEach((value, index) => console.log(`index = ${index}, value = ${value}`));

for...in

// 動作確認用のデータ作成
const obj = {
  '1': 100,
  '2': 200,
};

// for...inでkeyとvalueを取得
for (item in obj) {
  console.log(`key = ${item}, value = ${obj[item]}`);
}
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

JavaScript上で他言語プログラムを実行する

動機

卒研でとある解析プログラムを開発した.(CとPython)
後任のためにGUIで解析できるElectronデスクトップアプリを開発しようと決意.

ElectronどころかNodeアプリは初だった.Viewはまぁ良いとして解析のロジックをどう繋げようか悩んだ.
不得意なphpやjsに書き換えるのもアレなので,どうにかjs上でC,Pythonプログラムが実行できないかと思案したのが動機.

救える人

  • Nodeアプリ開発でjs上で他言語のプログラムを実行したい人

本編のネタバレすると,js上にサブプロセスを走らせる.ということをする.
要はコマンドプロンプトやらターミナルだ.なので,ターミナルで出来る作業はなんだって出来る.

これを言うと僕みたいな未熟者以外の方の耳もピクリと動くのではなかろうか.

本編

chile_processというNodeモジュールを使うと幸せになれる.
このモジュールはjs上でサブプロセスを生成できるという代物.

僕が作ったelectronアプリが例を抜粋するとこんな感じ.

index.html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>subroutine</title>
    <script>
        function subroutine() {
            let remote = require("electron").remote; // 以下3行はelectronアプリのpathを入手する例
            let app = remote.app;
            let path = app.getAppPath();

            const exec = require("child_process").exec;

            exec(path + "/violin_plot.bat"); // exec()の中にサブプロセスで実行したいコマンドをいれる.

        }
    </script>
</head>
<body>
    <button onclick="subroutine();">サブルーチン</button>
</body>
</html>

実際にはターミナルは表示されないので,標準出力とかは確認できないが,解析からのファイル操作とかCやpythonが得意なことで使うと効力を発揮するだろう.

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

【Vue.js】Formバリデーションを作ってみた【Javascript】

はじめに

インフラ系IT企業を2年でやめ、受託開発会社に勤務して約7ヶ月の3年目のエンジニアです。
今はほとんどインフラはやっておらず、フロントエンドばっかり書いています。勉強のためバリデーションでも作って見よう!と思って作りました。
※バリデーション自体はvuetifyやプラグイン使えばかんたんに実装できますが、自分で作るのって結構大事ですよね、プラグインに依存しないですし。

機能

1.フォームの送信ボタンをクリックするとバリデーションが発火する。
2.入力必須、文字数、形式(stringとかnumber)をチェックする。
3.エラーが発生してる状態だと送信できないようにする。

見た目

スクリーンショット 2020-02-27 13.45.20.png

formの見た目は適宜調整してください。

まずは、vueのformのソースからです。
formの部分は結構見ずらいので、コンポーネントに分けた方が良いと思います。

コード

Form

<template>
  <div class="form">
      <div class="form-item">
        <div class="form-item__label">
          {{ input.name.name }}
          <span class="form-item__require" v-if="input.name.require">必須</span>
        </div>
        <div class="form-item__input">
          <div class="underline">
            <input v-model="input.name.value" :id="input.name.name" type="text" placeholder />
            <label :for="input.name.name">{{ input.name.name }}</label>
          </div>
          <div class="validation-message">{{input.name.errorMessage[0]}}</div>
        </div>
      </div>
      <div class="form-item">
        <div class="form-item__label">
          {{ input.name_kana.name }}
          <span class="form-item__require" v-if="input.name_kana.require">必須</span>
        </div>
        <div class="form-item__input">
          <div class="underline">
            <input v-model="input.name_kana.value" :id="input.name_kana.name" type="text" placeholder />
            <label :for="input.name_kana.name">{{ input.name_kana.name }}</label>
          </div>
          <div class="validation-message">{{input.name_kana.errorMessage[0]}}</div>
        </div>
      </div>
      <div class="form-item">
        <div class="form-item__label">
          {{ input.mail.name }}
          <span class="form-item__require" v-if="input.mail.require">必須</span>
        </div>
        <div class="form-item__input">
          <div class="underline">
            <input v-model="input.mail.value" :id="input.mail.name" type="text" placeholder />
            <label :for="input.mail.name">{{ input.mail.name }}</label>
          </div>
          <div class="validation-message">{{input.mail.errorMessage[0]}}</div>
        </div>
      </div>
        <button type="button" class="submit-btn" @click="submit">登録</button>
  </div>
</template>

<script>
import {validation} from '@/utilities/validation/validation.js';
const form = {
  name: 'aaaaaaa',
  name_kana: 'a',
  mail: 'testes@gmail.com',
}

export default {
  data() {
    return {
      form,
      input: {
        name: {
          name: '名前',
          value: '',
          length: [1, 28],
          require: true,
          errorMessage: []
        },
        name_kana: {
          name: '名前(かな)',
          value: '',
          length: [1, 28],
          format: 'Hiragana',
          require: true,
          errorMessage: []
        },
        mail: {
          name: 'メールアドレス',
          value: '',
          format: 'Mail',
          length: [1, 28],
          require: false,
          errorMessage: []
        },
      }
    };
  },
  watch: {
    form: {
      handler(newValue) {
        for(let key in this.input) {
            this.input[key].value = newValue[key];
        }
      },
      immediate: true
    }
  },
  methods: {
    handleValidate(result){
      return validation(this.input);
    },
    submit() {
      const result = this.handleValidate(this.input);
      if (result.validStatus) {
        console.log('送信')
      }
    }
  }
};
</script>

<style lang="scss">
.form{
  padding: 24px 120px;
}
.form-item {
  min-height: 72px;
  padding: 16px 0;
  display: flex;
  &__label {
    font-size: 13px;
    color: black;
    text-align: left;
    font-weight: 600;
    text-align: right;
    min-width: 140px;
    max-width: 140px;
    margin-right: 12px;
  }
  &__input{
    width: 100%;
  }
  &__require{
    background-color: red;
    font-size: 10px;
    color: white;
    border-radius: 4px;
    display: inline-block;
    padding: 1px 4px;
    vertical-align: middle;
  }
}

.validation-message {
  font-size: 12px;
  color: red;
  margin-top: 8px;
  text-align: left;
}
.underline {
  border-bottom: 2px solid #bbb;
  padding: 0 8px 2px 8px;
  position: relative;
  &::before {
    left: 0;
    content: "";
    height: 5px;
    width: 2px;
    position: absolute;
    bottom: 0;
    background-color: #bbb;
  }
  &::after {
    content: "";
    height: 5px;
    width: 2px;
    position: absolute;
    right: 0;
    bottom: 0;
    background-color: #bbb;
  }
  input {
    position: relative;
    border: none;
    border-image-width: 0;
    outline: none;
    margin: 0;
    font-size: 12px;
    padding: 0;
    z-index: 1;
    -webkit-appearance: none;
    border-radius: 0;
    background-color: transparent;
    width: 100%;
    display: block;
    box-sizing: border-box;
    color: #111;
    font-family: "Roboto", sans-serif;
    font-weight: bold;
  }
  label {
    width: 100%;
    padding-bottom: 2px;
    cursor: default;
    font-weight: bold;
    position: absolute;
    font-size: 12px;
    font-family: "Roboto", sans-serif;
    top: -14px;
    left: 8px;
    opacity: 0;
    color: #777;
  }
}
.placeholder {
  user-select: none;
  position: absolute;
  left: 8px;
  bottom: 8px;
  color: #777;
  font-family: "Roboto", sans-serif;
  font-weight: normal;
  font-size: 18px;
  z-index: 0;
  opacity: 0.99;
}
.submit-btn {
  margin: 0 auto;
    display: block;
    position: relative;
    width: 160px;
    padding: 0.8em;
    text-align: center;
    text-decoration: none;
    color: #fff;
    background: #3A8BA8;
  &:hover {
    cursor: pointer;
    text-decoration: none;
    background:#fff;
  color:  #3A8BA8;
  border:solid 1px #3A8BA8;
  }
}

</style>

まず data() オプションのinputオブジェクトにv-modelやバリデーションで使う値を定義しています。
名前のフォームを例に上げて説明すると、、、

 name: {
    name: '名前', // フォームの名前を定義します。エラーメッセージやラベルで使用されます。
    value: '', // v-modelで使用します。
    length: [1, 28], // 入力値の長さを確認に使用します。1つ目の数字が最小文字数、2つ目は最大文字数です。定義しない場合はチェックを行いません。
    require: true, // 入力必須の確認に使用します。定義しない場合は入力必須チェックを行いません。
    errorMessage: [] // エラーメッセージの表示に使用します。配列なのでv-forで回せば全てのエラーを表示できます。
 },

これらを定義したあと、「登録」ボタンが押されたタイミングでバリデーションのメソッドが発火します。エラーがあればメッセージが表示されます。
エラーが無ければ任意のメソッドを実行させることができます。

※watchでform変数をみて、inputに代入していますが、これは編集画面等でバリデーションしたい場合に使用します。
vuex等でvalueをstateに入れてそれをinputのvalueにのみ入れます。

バリデーション本体

かなりコードが汚いとおもいますが、一応動きます。

// formatチェックで使用する正規表現です。必要に応じてファイルを分けたり、追加が可能です。
const ValidateSchema = {
  Number: {
    schema: /^[0-9]*$/,
    errorMessage: "は数字で入力してください"
  },
  NumberHyphen: {
    // eslint-disable-next-line no-useless-escape
    schema: /^[0-9\-]+$/,
    errorMessage: "に数字とハイフン以外が入力されています"
  },
  Hiragana: {
    schema: /^[ぁ-んー]+$/,
    errorMessage: "はひらがなで入力してください"
  },
  Mail: {
    // eslint-disable-next-line no-useless-escape
    schema: /^[a-zA-Z0-9.!#$%&'*+\/=?^_`{|}~-]+@[a-zA-Z0-9-]+(?:\.[a-zA-Z0-9-]+)*$/,
    errorMessage: "は正しい形式で入力してください"
  }
};

// 必須チェック
function requireCheck(input) {
  let result;
  let errorMessage;
    if (input.value.length <= 0 || input.value === null) {
      errorMessage = input.name + "は必須です。";
      result = { valid: false };
    } else {
      result = { valid: true };
      errorMessage = '';
    }
  return { errorMessage, ...result };
};

// 長さチェック
function lengthCheck(input) {
  const minLength = input.length[0];
  const maxLength = input.length[1];
  let errorMessage;
  let result;
  if (input.value.length >= minLength && input.value.length <= maxLength) {
    result = { valid: true };
    errorMessage = '';
  } else {
    errorMessage = input.name + "" + minLength + "文字以上" + maxLength + "文字以下で入力してください";
    result = { valid: false };
  }
  return { ...result, errorMessage };
};

// フォーマットチェック
function formatCheck(input) {
  const formatType = input.format;
  let errorMessage;
  let result;
  if (formatType && !input.value == '' || !input.value == null) {
    const validate = ValidateSchema[formatType].schema.test(input.value);
    if (validate) {
      result = { valid: true };
      errorMessage = '';
    } else {
      errorMessage = input.name + ValidateSchema[formatType].errorMessage;
      result = { valid: false };
    }
  } else {
    result = { valid: true };
    errorMessage = "";
  }
  return { ...result, errorMessage };
};

// エラーを初期化するメソッド
function clearErrorMessage(input) {
  return input.errorMessage = [];
}

// バリデーションメソッド
export const validation = (input) => {
  // 最初はエラーは0
  let errors = 0;
  const result = input;
  for (let key in input) {
    //エラーを初期化
    clearErrorMessage(result[key], errors);
    // 入力必須が設定されていた場合のみ実行
    if (input[key].require) {
      const requireCheckResult = requireCheck(result[key]);
      if (requireCheckResult.valid != true) {
        result[key].errorMessage.push(requireCheckResult.errorMessage);
        errors++;
      }
    }
    // 入力必須が設定されていて、長さチェックが設定されていた場合のみ実行
    if (input[key].length && input[key].require) {
      const lengthCheckResult = lengthCheck(result[key]);
      if (lengthCheckResult.valid != true) {
        result[key].errorMessage.push(lengthCheckResult.errorMessage);
        errors++;
      }
    }
    // フォーマットが設定されていた場合のみ実行
    if (input[key].format) {
      const formatCheckResult = formatCheck(result[key]);
      if (formatCheckResult.valid != true) {
        result[key].errorMessage.push(formatCheckResult.errorMessage);
        errors++;
      }
    }
    if (errors == 0) {
      clearErrorMessage(result[key], errors);
    }
  }
  if (errors === 0) {
    return { validStatus: true };
  }
  return { validStatus: false, input: { ...result } };
};

コンポーネントの方で定義したinputのオブジェクトを単純にforでまわして一つひとつバリデーションしています。
最終的にerrorsが0になった場合のみvalidStatusをtrueにして返します。

まとめ

かなり遠回りなコードだと思いますが、一応バリデーションを実行することができます。
改善することとして、バリデーションのスキーマをファイルに分けたり、formをコンポーネント化したりすることですね。
何か不具合等あればコメントいただければと思います。

今後もjavascript頑張っていきたいです。

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

「チーム共有機能・Views生成時の命名規則修正」LaravelDB.com

◇Laravel DB.com を初めて知った人はこちらから

1.Laravel DB.com ってなに?前回の紹介記事です!

2.Qiita記事LaravelDB.comの紹介 >>

3.次にLaravelDB.comを知った人は以下へどうぞ。

4.LaravelDB.comへログイン >>

◇NewUpdate[2020-02-25~]

1.Update:Views生成時フォルダ名の命名規則

以前と現在のLaravelDB.comのView生成時の命名規則は以下です。

記法 複/単
以前 キャメルケース 複数形 testDemos
現在 スネークケース 単数形 test_demo

※キャメルケースは、複合語をひと綴りとして、要素語の最初を大文字で書き表す記法。
※アンダースコア( _ )を区切記号として単語をつなげる記法。

何故、いま「Viewsの命名規則」を変えたのか?
Auth関連の処理を追加・変更しようとする際に「現在の記法(スネークケース)」でないと動作しないケースがあるため変更しました。

2.New:チーム共有機能(他のメンバーとER図を共有)

LaravelDB.comをリリース後に ”Feedbackで一番多かった” のが、「Team開発やメンターとのオンラインMTG用にER図を共有したい」でした。

「どうやったら?シンプルに実装でき、ユーザーが簡単に操作できるか?」の仕様検討が最も時間がかかりました。
数日間悩んだ結果、一つの方法を昨日考えつきました。仕様と実装方法が見えてきたらそこからは1日半程度で完成し、その翌日にはリリースしました。スピードは時間を有意義に使うための重要なスキルです。これで、オンライン上でテーブルの設計が共有でき、CRUDが簡単に生成できることでしょう。
また 追加機能・改修等があれば今後もアップデート記事を書いていきます。

【シェアData「送信側」】

テーブル設計をシェアする機能のことです。

1 [シェアData]作成


POINT:
この時点で共有データが作成されます。
見せたい相手にIDを渡しておいて、変更があれば「Create a [Share ID]」ボタンを押すと毎度データ更新されることを知っておきましょう! 「データ更新したので見てください!」って後から言えるってことですね。

2 [シェアData] IDをコピー

ここでコピーしたIDを相手に知らせます。

【シェアData 「受信側」】

1 [シェアData]読み込み

相手は送られてきた[シェアData]IDを貼り付けます。
こちらのIDを知っていれば誰でも読み込めます!見て欲しい人に渡しましょう!
※LOGIN(Googleアカウントで)しないと見れないことは認識しておいてください。

2.「Read」ボタンをクリックしてデータを受信表示しましょう。

3.シェアデータの複製が完了!!

受信側にデータが入りました!受信側もそのデータを活用できるようになります。
チーム・メンタリング等のケースでも利用可能です。

※受信後は「別名を付けて保存しておくと良いでしょう!」


LaravelDB.com解説ページ一覧

コード書かずに超スピード開発~(DEMO動画あり)~最新版『 Laravel DB.com 』

https://qiita.com/daisu_yamazaki/items/068595670bdc2b6fe3fc

LaravelDB.com 対応カラム一覧

https://qiita.com/daisu_yamazaki/items/92dc3cc599a264c3fb0f

LaravelDB.com テーブル命名ルール

https://qiita.com/daisu_yamazaki/items/1cb5987cc6d1008def82

LaravelDb.com integerの注意点

https://qiita.com/daisu_yamazaki/items/f2e6d58cfa20fa81fd54

LaravelDB.com Faker(テストデータ投入)

https://qiita.com/daisu_yamazaki/items/57669e8fa2c256d85c95

Twitter

LaravelDB.com

以上

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

NewUpdate!!「チーム共有機能・Views生成時の命名規則修正」LaravelDB.com

◇Laravel DB.com を初めて知った人はこちらから

1.Laravel DB.com ってなに?前回の紹介記事です!

2.Qiita記事LaravelDB.comの紹介 >>

3.次にLaravelDB.comを知った人は以下へどうぞ。

4.LaravelDB.comへログイン >>

◇NewUpdate[2020-02-25~]

1.Update:Views生成時フォルダ名の命名規則

以前と現在のLaravelDB.comのView生成時の命名規則は以下です。

記法 複/単
以前 キャメルケース 複数形 testDemos
現在 スネークケース 単数形 test_demo

※キャメルケースは、複合語をひと綴りとして、要素語の最初を大文字で書き表す記法。
※アンダースコア( _ )を区切記号として単語をつなげる記法。

何故、いま「Viewsの命名規則」を変えたのか?
Auth関連の処理を追加・変更しようとする際に「現在の記法(スネークケース)」でないと動作しないケースがあるため変更しました。

2.New:チーム共有機能(他のメンバーとER図を共有)

LaravelDB.comをリリース後に ”Feedbackで一番多かった” のが、「Team開発やメンターとのオンラインMTG用にER図を共有したい」でした。

「どうやったら?シンプルに実装でき、ユーザーが簡単に操作できるか?」の仕様検討が最も時間がかかりました。
数日間悩んだ結果、一つの方法を昨日考えつきました。仕様と実装方法が見えてきたらそこからは1日半程度で完成し、その翌日にはリリースしました。スピードは時間を有意義に使うための重要なスキルです。これで、オンライン上でテーブルの設計が共有でき、CRUDが簡単に生成できることでしょう。
また 追加機能・改修等があれば今後もアップデート記事を書いていきます。

【シェアData「送信側」】

テーブル設計をシェアする機能のことです。

1 [シェアData]作成


POINT:
この時点で共有データが作成されます。
見せたい相手にIDを渡しておいて、変更があれば「Create a [Share ID]」ボタンを押すと毎度データ更新されることを知っておきましょう! 「データ更新したので見てください!」って後から言えるってことですね。

2 [シェアData] IDをコピー

ここでコピーしたIDを相手に知らせます。

【シェアData 「受信側」】

1 [シェアData]読み込み

相手は送られてきた[シェアData]IDを貼り付けます。
こちらのIDを知っていれば誰でも読み込めます!見て欲しい人に渡しましょう!
※LOGIN(Googleアカウントで)しないと見れないことは認識しておいてください。

2.「Read」ボタンをクリックしてデータを受信表示しましょう。

3.シェアデータの複製が完了!!

受信側にデータが入りました!受信側もそのデータを活用できるようになります。
チーム・メンタリング等のケースでも利用可能です。

※受信後は「別名を付けて保存しておくと良いでしょう!」


LaravelDB.com解説ページ一覧

コード書かずに超スピード開発~(DEMO動画あり)~最新版『 Laravel DB.com 』

https://qiita.com/daisu_yamazaki/items/068595670bdc2b6fe3fc

LaravelDB.com 対応カラム一覧

https://qiita.com/daisu_yamazaki/items/92dc3cc599a264c3fb0f

LaravelDB.com テーブル命名ルール

https://qiita.com/daisu_yamazaki/items/1cb5987cc6d1008def82

LaravelDb.com integerの注意点

https://qiita.com/daisu_yamazaki/items/f2e6d58cfa20fa81fd54

LaravelDB.com Faker(テストデータ投入)

https://qiita.com/daisu_yamazaki/items/57669e8fa2c256d85c95

Twitter

LaravelDB.com

以上

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

Update「チーム共有機能・Views生成時の命名規則修正」LaravelDB.com

◇Laravel DB.com を初めて知った人はこちらから

1.Laravel DB.com ってなに?前回の紹介記事です!

2.Qiita記事LaravelDB.comの紹介 >>

3.次にLaravelDB.comを知った人は以下へどうぞ。

4.LaravelDB.comへログイン >>

◇NewUpdate[2020-02-25~]

1.Update:Views生成時フォルダ名の命名規則

以前と現在のLaravelDB.comのView生成時の命名規則は以下です。

記法 複/単
以前 キャメルケース 複数形 testDemos
現在 スネークケース 単数形 test_demo

※キャメルケースは、複合語をひと綴りとして、要素語の最初を大文字で書き表す記法。
※アンダースコア( _ )を区切記号として単語をつなげる記法。

何故、いま「Viewsの命名規則」を変えたのか?
Auth関連の処理を追加・変更しようとする際に「現在の記法(スネークケース)」でないと動作しないケースがあるため変更しました。

2.New:チーム共有機能(他のメンバーとER図を共有)

LaravelDB.comをリリース後に ”Feedbackで一番多かった” のが、「Team開発やメンターとのオンラインMTG用にER図を共有したい」でした。

「どうやったら?シンプルに実装でき、ユーザーが簡単に操作できるか?」の仕様検討が最も時間がかかりました。
数日間悩んだ結果、一つの方法を昨日考えつきました。仕様と実装方法が見えてきたらそこからは1日半程度で完成し、その翌日にはリリースしました。スピードは時間を有意義に使うための重要なスキルです。これで、オンライン上でテーブルの設計が共有でき、CRUDが簡単に生成できることでしょう。
また 追加機能・改修等があれば今後もアップデート記事を書いていきます。

【シェアData「送信側」】

テーブル設計をシェアする機能のことです。

1 [シェアData]作成


POINT:
この時点で共有データが作成されます。
見せたい相手にIDを渡しておいて、変更があれば「Create a [Share ID]」ボタンを押すと毎度データ更新されることを知っておきましょう! 「データ更新したので見てください!」って後から言えるってことですね。

2 [シェアData] IDをコピー

ここでコピーしたIDを相手に知らせます。

【シェアData 「受信側」】

1 [シェアData]読み込み

相手は送られてきた[シェアData]IDを貼り付けます。
こちらのIDを知っていれば誰でも読み込めます!見て欲しい人に渡しましょう!
※LOGIN(Googleアカウントで)しないと見れないことは認識しておいてください。

2.「Read」ボタンをクリックしてデータを受信表示しましょう。

3.シェアデータの複製が完了!!

受信側にデータが入りました!受信側もそのデータを活用できるようになります。
チーム・メンタリング等のケースでも利用可能です。

※受信後は「別名を付けて保存しておくと良いでしょう!」


LaravelDB.com解説ページ一覧

コード書かずに超スピード開発~(DEMO動画あり)~最新版『 Laravel DB.com 』

https://qiita.com/daisu_yamazaki/items/068595670bdc2b6fe3fc

LaravelDB.com 対応カラム一覧

https://qiita.com/daisu_yamazaki/items/92dc3cc599a264c3fb0f

LaravelDB.com テーブル命名ルール

https://qiita.com/daisu_yamazaki/items/1cb5987cc6d1008def82

LaravelDb.com integerの注意点

https://qiita.com/daisu_yamazaki/items/f2e6d58cfa20fa81fd54

LaravelDB.com Faker(テストデータ投入)

https://qiita.com/daisu_yamazaki/items/57669e8fa2c256d85c95

Twitter

LaravelDB.com

以上

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

おみくじでjavascriptを勉強

次の現場でjavascriptを使うことになったので、少しでも触れるようになっておこうと勉強し始めました。
手始めに、よくある「おみくじ」アプリを作ってみます
アプリと言えるほど大層なものではなく、ただweb上で表示するだけですが笑

htmlコード(index.html)

<html>
    <head>
        <meta http-equiv="content-type" charset="utf-8">
    </head>
    <body>
        <h1>簡単おみくじ</h1>
        <input type="button" id="getResult" value="ボタンを押すとおみくじが引けるよ">
        <div id="result"></div>
        <script src="script.js"></script>
    </body>
</html>

javascriptを適用したい場所にscriptを差し込んでやると、そこに反映してくれるようです。
でもcssと同様で、headに書くのが一般的なのかな?とも。
これは今後勉強していって気づけばいいですね。

javascriptコード(script.js)

let omikuji = {
    items: ["大吉", "", "中吉", "小吉", "末吉", ""],
    getResult: function() {
        let results = this.items;
        return results[Math.floor(Math.random() * results.length)]
    }
}
//console.log(omikuji.getResult())

let getResult = document.getElementById("getResult");
let result = document.getElementById("result");

getResult.addEventListener("click", function() {
    let done = omikuji.getResult();
    switch (done) {
        case "大吉":
            result.innerHTML = "おめでとう!結果は「" + done + "」でした";
            break;
        default:
            result.innerHTML = "結果は「" + done + "」でした";
    }
})

変数の宣言、条件分岐、関数の作成、HTMLの操作を取り入れました。
基礎的な事は豊富に学べたかなと思います。

変数の宣言

javascriptではletで変数を宣言する必要があるようです。
pythonでは宣言なしで使えたので、少し煩わしさがあります。
なお、定数を使用する際はconstで宣言するみたいです。
事前に宣言する分、管理しやすいのがメリットですね。

条件分岐

他の言語でもあるif文でも良かったのですが、より簡単にまとめられるswitch文を今回は使いました。
「if hoge = hogehoge」と書くより、caseで結果だけ書く方が楽ですね。
ここでは、それぞれのcaseでbreakを書くことが注意です。
仮に下に書いたcaseにも該当すると、下が優先されてしまうからです。
caseに該当しない処理はdefaultで書いてあげます

関数

関数はfunctionで定義してあげます。
またitems: []のように関数内で変数を宣言する際は、
let 変数名 =ではなく変数名:になるのも注意です。

Math.floor()は、整数に直してくれます
Math.random()は、0-1内でランダム数字を作ります。

HTMLの操作

HTML側の操作をできるのがjavascriptの醍醐味です。
今回はたくさんある操作の中で、3つ使ってみました。

document.getElementById(htmlのid)
これはhtmlで宣言したidをとってこれます。
つまり該当のid箇所に操作を加えることができます。

addEventListener(“ユーザー動作”, 操作)
ユーザーの動作を引き金として、次の操作を実行できます。
今回は”ユーザー動作”にclickを入れました。
これはユーザーが画面クリックした時を、起点にしたいがためです。

innerHTML
HTML側に文章を渡すことができます。
html表記がそのまま使えるのでかなり便利ですね。

実行結果はこうなります

EA1E6052-F8A8-4786-B685-F6910538705C.jpeg

9E1600C5-884E-4440-861E-1C6C91BCF9EC.jpeg

以上です!

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

Next.js のプロジェクトにGTMを組み込む方法

意外と情報がなかったので後世のために記す。

react-gtm-module というライブラリにお世話になった。
使わない場合は _document.js に dangerouslySetInnerHTML したりでもいける。はず。

Next.js での設定

まず npm install react-gtm-module --saveyarn add react-gtm-module する。

そして _app.tsx に次のコードを埋め込む

import TagManager from 'react-gtm-module';

class MyApp extends App {
  componentDidMount() {
    // gtmId に自分のGTMアカウントのID入れてください
    TagManager.initialize({ gtmId: 'GTM-XXXXXX' });
  }

  render() {
    。。。
  }
}

これでタグは配信されるようになる。

が、これだけだとクライアントサイドルーティングのPVが計測できない(History APIで更新しているだけなのでタグが発火されないから)。Next.jsを使っていると基本的にユーザの元に届いた時点でSPAとして振舞うようになると思うのでそれに対策する必要がある。

GTM上でページ遷移時のPVを取るためのトリガーを作る

「履歴の変更」というトリガーを仕込んであげるといい。
https://support.google.com/tagmanager/answer/7679322?hl=ja

スクリーンショット 2020-02-27 10.18.32.png

これで公開して GTM のプレビューで見ると History というイベントが計測されていることを確認できる。

スクリーンショット 2020-02-27 10.19.38.png

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

JavaScriptでIdentifier '<変数名>' has already been declared が発生する

現象

シンプルなHTML+JavaScriptの構成にて以下のエラーが発生。
Uncaught SyntaxError: Identifier '<変数名>' has already been declared

エラー内容的には、「変数がすでに宣言されているよ!」らしいが、2重で宣言してしまっているような個所は見当たらない。

しかもこのエラーは常に先頭行にある変数に対してのみ発生していて、
先頭行の変数を削除すると、その次にある変数で同じエラーが発生する。

原因

HTMLでJavaScriptファイルを2回読み込んでしまっていた。

<!-- 省略 -->
        </div>
      </div>
      <script src="script.js"></script><!-- 1回目 -->
    </div>
  </div>
  <div class="text"></div>
</body>
<script src="https://code.jquery.com/jquery-3.3.1.js"></script>
<script type="text/javascript" src="script.js"></script><!-- 2回目 -->
</html>

盲点。気づくまで30分くらいかかった。
これ、やったことある人いるよね。

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

PHPとjavascriptで営業日カレンダー

phpとjavascriptで営業カレンダーを作る

完成した表示
スクリーンショット 2020-02-27 9.32.01.png
仕様
・休みは赤色にする
・定休日:祝日と日曜、木曜
・アイコンクリックで表示月変更

設計
・PHPでカレンダーを構築する配列をJSONで出力
・ajaxで受け取り出力する。

1.祝日配列のつくる

内閣府のページに祝日のcsvがあるので、そこからダウンロードする。
https://www8.cao.go.jp/chosei/shukujitsu/gaiyou.html
※csvはUTF-8に変換して保存。

calendar.php
function get_public_holidays(){
    $path = "./syukujitsu.csv";
    $csv = new SplFileObject($path);
    $csv->setFlags(SplFileObject::READ_CSV);
    $holidays = [];
    foreach ($csv as $key => $line){
        $holidays[$line[0]] = $line[1];
    }
    return $holidays;
}

2.カレンダーを構築する配列をつくる

calendar.php
function make_date_list($year,$month){

    $regular_holiday = [0,4]; //定休日:曜日
    $public_holidays = get_public_holidays(); //祝日

    $target = new \DateTime("{$year}-{$month}-01");
    $date = [];
    for($i = 0; $i < intval($target->format('t')); $i++){

        if($i > 0) $target->modify('+1day');
        //祝日
        if(isset($public_holidays[$target->format('Y/n/d')])){
            $holiday = true;
        //定休日
        }else if(in_array($target->format('w'),$regular_holiday)){
            $holiday = true;
        }else{
            $holiday = false;
        }

        $dates[$i] = [
            'day' => $target->format('d'),
            'week' => $target->format('w'),
            'holiday' => $holiday,
        ];

    }

    /*カレンダーの空欄箇所*/
    $first_date = current($dates);
    $end_date = end($dates);

    $damy_num = intval($first_date['week']);
    if($damy_num > 0){
        $damy = [];        
        for($i = $damy_num - 1;0 <= $i;$i--){
            array_unshift($dates,['week'=>$i,'day'=>'&nbsp;']);
        }    
    }

    $damy_num = intval($end_date['week']);
    if($damy_num < 6){
        $damy = [];        
        for($i = $damy_num; $i < 6;$i++){
            array_push($dates,['week'=>$i,'day'=>'&nbsp;']);
        }
    }

    return $dates;
}

3.リクエストがよる出力

calendar.php
if(isset($_GET['y']) and $_GET['y']){
    $year = $_GET['y'];
}else{
    $year = date('Y');
}

if(isset($_GET['m']) and $_GET['m']){
    $month = $_GET['m'];
}else{
    $month = date('m');
}

$dates = make_date_list($year,$month);

echo json_encode($dates);

4.javascriptでのカレンダー構築

2ヶ月先までの表示にしています。

calendar.js
var nowDate;
var year;
var month;

$(function(){
    nowDate = new Date();
    year = nowDate.getFullYear(); // 年
    month = nowDate.getMonth() + 1; // 月

    MakeCalendar();
});

function prev(){
    if(month === 1){
        month = 12;
        year--;
    }else{
        month--;
    }
    MakeCalendar();

}

function next(){
    if(month === 12){
        month = 1;
        year++;
    }else{
        month++;
    }
    MakeCalendar();
}

function MakeCalendar(){
    $.ajax({
        url: 'calender.php?y='+year+'&m='+month,
        dataType: 'json',
        timeout: 10000,  
        success: function(json) {

            var c = '<div class="cal"><div class="cal_header">';
            if(nowDate.getFullYear() <= year && (nowDate.getMonth() + 1) < month ){
                c += '<a href="" onClick="prev();return false;" class="cal_prev"><img src="./images/cal_prev.png" alt="前の月" width="19"></a>';
            }else{}

            if(nowDate.getFullYear() >= year && (nowDate.getMonth() + 3) > month ){
                c += '<a href="" onClick="next();return false;" class="cal_next"><img src="./images/cal_next.png" alt="次の月" width="19"></a>'
            }else{}

            c += '<strong>'+year+''+month+'月</strong>';
            c += '</div>';
            c += '<div class="cal_body">';
            c += '<table class="table_cal">';
            c += '<thead><tr><th>日</th><th>月</th><th>火</th><th>水</th><th>木</th><th>金</th><th>土</th></tr></thead>';

            jQuery.each(json, function(i, date) {

                if(date.week === '0'){
                    c += '<tr>';
                }else{}
                if(date.holiday === true){
                    c += '<td><span class="closed">'+date.day+'</span></td>';
                }else{
                    c += '<td>'+date.day+'</td>';
                }

                if(date.week === '6'){
                    c += '</tr>';
                }else{}

            });

            c += '</tbody></table></div></div>';

            $('#calendar').html(c);

        },
         error: function(xhr, textStatus, error) {
            alert('ERR');
        }
    });

}

4.表示

表示する箇所にタグとCSSを構築して完成。

sample.html
<div id="calendar"></div>

sample.css
.cal{background:#fff;box-shadow:2px 2px 4px rgba(0,0,0,0.2);}
.cal_header{padding:15px 13px;border-bottom:1px solid #ddd;}
.cal_header a,.cal_header span{display:block;}
.cal_header strong{display:block;text-align:center;font-size:1.3rem;color:#005ca2;line-height:19px;}
.cal_prev{float:left;cursor:pointer;}
.cal_next{float:right;cursor:pointer;}
.cal_body{padding:10px 15px;text-align:center;}

.table_cal{width:100%;border-collapse:collapse;}
.table_cal th,.table_cal td{font-size:1.1rem;text-align:center;height:30px;min-width:31px;}

.today{font-weight:bold;text-decoration:underline;}
.closed{display:inline-block;width:22px;height:22px;background:#eb6e8f;color:#fff;border-radius:50%;line-height:23px;}

.cal_bottom{font-size:1.1rem;margin:10px 0 15px;}
.cal_bottom span{vertical-align:middle;margin-right:4px;}

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

開いているウインドウの全タブのページタイトルとURLを取得するChrome拡張作った

はじめに

作り始めてから色々調べてたら「GetTabInfo」など既に公開されてるのもので実現可能でした。ただ、一度Chrome拡張を自作することにこそ意味があると思って開発を進めました。
あとちなみに今回でChrome拡張の開発は初めてでした。まあ、HTMLやJavaScriptにはある程度慣れてるので躓いたのは普通のサイトならできてもChrome拡張では制限されてできないことへの対策ですかね・・・。

それはそうと、なんで必要なん?

まずひとつ、私自身がタブ魔で、常に開いているタブの数が半端ない(開発中に開いてる全ウインドウのタブの数をコンソール出力したら80くらいあったわ。)というのはある。そのせいでめちゃくちゃChromeちゃんがRAMをもりもり食べてるのは仕方ない。

あとはまあ、少し前からQiitaでこうやって記事書いたりしてますが、いちいち全ての参考文献のwebページのタイトルとURLをコピペするのは面倒くさすぎる。一応今回で完成には至ったので、今回の記事からワンクリックで参考文献が貼り付けられます。
アルル「やったね、カーくん!!」
カーバンクル「ぐぐー!」
というぷよキャラの勝利セリフが一瞬横切りました。が、見なかったことにしましょう。

機能紹介

現時点ではまだ設定を変える機能は未実装なので直接JavaScriptのコードを弄ることになりますが、今後、設定を変えられるようにする予定です。自分が使いたいので。笑

テンプレート機能で表現の幅が広がる!

getTitleAndURL.js15行目の変数を書き換えることで、コピーしたいタイトル、URLの形式(コロン区切りやMarkDown形式など)に変えることができます。

%%title%%:ページのタイトルに置換されます。
%%URL%%:ページのURLに置換されます。

仕様上、「'」「"」「\」を含めるには、エスケープシーケンス「\'」「\"」「\」を用いる必要があります。

例えば、MarkDown形式に対応させる(そのまま貼り付けて使えるようにする)には、[%%title%%](%%URL%%)のようにします。デフォルトでは、[%%title%%](%%URL%% \"%%title%%\")となっており、aタグのtitle属性を付与させています。

区切り文字編集機能でより快適に!

getTitleAndURL.js14行目の変数を書き換えることで、一つ一つのページのタイトル&URL間の区切りを指定できます。これにより、コンマ区切りなどにもできます。デフォルトでは改行となっています。

これがなくっちゃ始まらない!開いている全てのタブのページ情報のクリップボードへのコピー!

getTitleAndURLofALLTabsを動かしたウィンドウ内の全てのページのタイトルとURL(テンプレートと区切り文字に基づく)を表示し、「copy」ボタンのクリックでクリップボードにコピーすることができます。

ソースコード

ひとまず仮のものなのでUIなどは非常にシンプルです。CSS不使用なのでHTML初心者に優しい(?)
GitHubでも公開しています。→yukuduri/getTitleAndURLofALLTabs

manifest.json
{
  "name": "get Title&URL of ALLTabs",
  "author": "yukuduri",
  "version": "1.0.0",
  "description": "開いているウインドウ内のすべてのタブのタイトルとURLを取得します。",
  "icons": {
    "16": "icon16.png",
    "48": "icon48.png",
    "128": "icon128.png"
  },
  "browser_action":{
    "default_icon": {
      "19": "icon19.png"
    },
    "default_title": "get Title&URL of ALLTabs",
    "default_popup": "popup.html"
  },
  "permissions": [
    "activeTab",
    "tabs",
    "clipboardWrite"
  ],
  "manifest_version": 2
}
popup.html
<!DOCTYPE HTML>
<html>
  <head>
    <meta charset="utf-8">
    <script src="getTitleAndURL.js"></script>
  </head>
  <body>
    <h2>get Title&URL of ALLTabs</h2>
    <label>現在のウインドウのタブ数:<input id="numOfTabs" type="number" readonly></label><br><br>
    <label>取得したタイトルとURL:<textarea id="txt"></textarea></label><br>
    <button id="copy">copy</button>
  </body>
</html>
getTitleAndURL.js
const createTextFromTemplate = (title, url, template) => {
  let txt = template;

  txt = txt.replace(/%%title%%/g,title);
  txt = txt.replace(/%%URL%%/g,url);
  return txt;
}


const run = () => {
  //現在のウインドウのタブをすべて取得
  chrome.tabs.query({windowId: chrome.windows.WINDOW_ID_CURRENT},(tabs) => {
    let txt = '';
    const delimiter = '\n';  //区切り文字
    const template = '[%%title%%](%%URL%% \"%%title%%\")'; //テンプレ

    document.querySelector('#numOfTabs').value = tabs.length;

    tabs.forEach((tab,i) => {
      if(i!=0) txt += delimiter;  //最初は区切り文字不要
      console.log(tab.title+" "+tab.url);
      txt += createTextFromTemplate(tab.title,tab.url,template);
    });

    document.querySelector('#txt').value = txt;

  });
}

const copy = () => {
  const copyText = document.querySelector('#txt');
  copyText.select();
  document.execCommand('copy');
}

window.addEventListener('load',()=>{
  run();
  document.querySelector("#copy").addEventListener("click", copy);
})

簡単な解説

manifest.json

細かいところは参考文献を見ていただくことにして、需要度の高いものをいくつか。

"permissions""activeTab","tabs","clipboardWrite"の3つを指定。"activeTab"は不必要なときに動作させないため、"tabs"は実行時のタブ以外の情報を取り出すために必要、"clipboardWrite"document.execCommand('copy');を使うなら必須ではないが付けておいてね、ってことみたいなので付けた。

あ、ちなみにアイコンはフリーソフトのInkscapeで作りました。

popup.html

省略。次のgetTitleAndURL.jsのときに少し触れます。

getTitleAndURL.js

const createTextFromTemplate = (title, url, template) => {
  let txt = template;

  txt = txt.replace(/%%title%%/g,title);
  txt = txt.replace(/%%URL%%/g,url);
  return txt;
}

templateに含まれる文字列「%%title%%」を全てtitleに、「%%URL%%」を全てurlに、それぞれ置換します。

const run = () => {
  //現在のウインドウのタブをすべて取得
  chrome.tabs.query({windowId: chrome.windows.WINDOW_ID_CURRENT},(tabs) => {
    let txt = '';
    const delimiter = '\n';  //区切り文字
    const template = '[%%title%%](%%URL%% \"%%title%%\")'; //テンプレ

    document.querySelector('#numOfTabs').value = tabs.length;

    tabs.forEach((tab,i) => {
      if(i!=0) txt += delimiter;  //最初は区切り文字不要
      console.log(tab.title+" "+tab.url);
      txt += createTextFromTemplate(tab.title,tab.url,template);
    });

    document.querySelector('#txt').value = txt;

  });
}

現在のウインドウのタブをすべて取得して実行します。chrome.windows.WINDOW_ID_CURRENTには今開いているブラウザウィンドウのidが格納されているのでこれを渡せば今開いているウインドウの全てのタブを取得できます。ここではtabstabの配列が入っています。詳しくは省略しますが、ともかく、tab.titleでそのタブのページタイトルtab.urlでURLが取得できます。あとはそれを利用してコピーするための文字列を生成します。生成したらtextareaにぶち込みます。ついでに今のウインドウで開いてるタブ数を表示しようとしましたが、Chrome拡張の制限から、popup.htmlのHTMLをinnerHTMLなどでは扱えないようでした。なのでinput要素で実現しています。

const copy = () => {
  const copyText = document.querySelector('#txt');
  copyText.select();
  document.execCommand('copy');
}

生成して出力された文字列をクリップボードにコピーします。
`document.execCommand('copy');'は全ての機種で動作するわけではなかったはずですが、まあPC版Chromeでの動作であればまず問題ないはずなので大丈夫でしょう。

window.addEventListener('load',()=>{
  run();
  document.querySelector("#copy").addEventListener("click", copy);
})

アドレスバー横のChrome拡張のアイコンをクリックしてpopup.htmlが表示されるときに実行する場所です。開いたと同時に取得からtextareaへの挿入を終わらせてしまいます。
あとは、copyボタンがクリックされたときにクリップボードにコピーさせるだけです。

owata

今回は以上になります。
Chrome拡張の設定の件でまたもう少しやって再び記事を書こうかなとか思ってますが、徹夜で作業してましたし眠いのでこれから寝ます。
誤字とかあったら起きてから直しますので、コメントに書いていただけるなどすると助かります。おやすみなさい。

参考文献

今回作成した拡張機能で生成した文字列を以下に貼り付けてしまいましょう。
今回も、多くの記事を参考にさせていただきました。ありがとうございます。

ページのタイトルとURLを取得するChrome拡張を作った。 - Qiita
Chrome 拡張機能のマニフェストファイルの書き方 - Qiita
Chromeブラウザの拡張機能を作ってみたい初心者向けに開発方法を紹介!【サンプルあり】 - Qiita
Chrome拡張機能作成〜超基礎編〜 - Qiita
特定の文字列を全て置換する[Javascript] - Qiita
Chromeアドオン開発のチュートリアル: ページの背景色を変えるアドオン(Getting Started Tutorial) - 主に言語とシステム開発に関して
クリップボードとのやりとり - Mozilla | MDN
EventTarget.addEventListener() - Web API | MDN
chrome.windows - Google Chrome
Declare Permissions - Google Chrome
The activeTab permission - Google Chrome
chrome.windows-Google Chrome

あ、これは以前私が書いた記事ですが、一通りまとまっているので自分でも重宝しています。
JavaScript基礎文法 - Qiita

ちなみにこんな感じで取得できています。

[ページのタイトルとURLを取得するChrome拡張を作った。 - Qiita](https://qiita.com/a01sa01to/items/bd7b18b4ec3dc6c46b32 "ページのタイトルとURLを取得するChrome拡張を作った。 - Qiita")
[Chrome 拡張機能のマニフェストファイルの書き方 - Qiita](https://qiita.com/mdstoy/items/9866544e37987337dc79#options_page "Chrome 拡張機能のマニフェストファイルの書き方 - Qiita")
[Chromeブラウザの拡張機能を作ってみたい初心者向けに開発方法を紹介!【サンプルあり】 - Qiita](https://qiita.com/guru_taka/items/37a90766f4f845e963e5 "Chromeブラウザの拡張機能を作ってみたい初心者向けに開発方法を紹介!【サンプルあり】 - Qiita")
[Chrome拡張機能作成〜超基礎編〜 - Qiita](https://qiita.com/Ryo_Suzuki/items/d247008888ef67bdeda8 "Chrome拡張機能作成〜超基礎編〜 - Qiita")
[特定の文字列を全て置換する[Javascript] - Qiita](https://qiita.com/DecoratedKnight/items/103ab57431b6c448e535 "特定の文字列を全て置換する[Javascript] - Qiita")
[Chromeアドオン開発のチュートリアル: ページの背景色を変えるアドオン(Getting Started Tutorial) - 主に言語とシステム開発に関して](https://language-and-engineering.hatenablog.jp/entry/2018/10/22/Chrome%E3%82%A2%E3%83%89%E3%82%AA%E3%83%B3%E9%96%8B%E7%99%BA%E3%81%AE%E3%83%81%E3%83%A5%E3%83%BC%E3%83%88%E3%83%AA%E3%82%A2%E3%83%AB%EF%BC%9A_%E3%83%9A%E3%83%BC%E3%82%B8%E3%81%AE "Chromeアドオン開発のチュートリアル: ページの背景色を変えるアドオン(Getting Started Tutorial) - 主に言語とシステム開発に関して")
[クリップボードとのやりとり - Mozilla | MDN](https://developer.mozilla.org/ja/docs/Mozilla/Add-ons/WebExtensions/Interact_with_the_clipboard "クリップボードとのやりとり - Mozilla | MDN")
[EventTarget.addEventListener() - Web API | MDN](https://developer.mozilla.org/ja/docs/Web/API/EventTarget/addEventListener "EventTarget.addEventListener() - Web API | MDN")
[chrome.windows - Google Chrome](https://developer.chrome.com/extensions/windows#current-window "chrome.windows - Google Chrome")
[Declare Permissions - Google Chrome](https://developer.chrome.com/extensions/declare_permissions "Declare Permissions - Google Chrome")
[The activeTab permission - Google Chrome](https://developer.chrome.com/extensions/activeTab#what-activeTab-allows "The activeTab permission - Google Chrome")
[chrome.windows-Google Chrome](https://developer.chrome.com/extensions/windows#property-WINDOW_ID_CURRENT "chrome.windows-Google Chrome")
[JavaScript基礎文法 - Qiita](https://qiita.com/yukuduri/items/cff4a1f9c85114600425 "JavaScript基礎文法 - Qiita")
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

javascriptでslackにメッセージを送信する方法

javascriptでslackにメッセージを送信する方法をまとめました。

前提条件

  • npmがインストールされていること
  • slackのapiキーが分かっていること

インストール

npmコマンドでモジュールをインストール

$ npm i --save axios

使い方

ファイルの作成

touchコマンドでtest.jsファイルを作成

$ touch test.js

設定

test.js
pathにはslackのapiが入ります。

const axios = require('axios')

const slack = async (path, channel, username, text, iconEmoji) => {
  const data = `payload={
    "channel": "${channel}",
    "username": "${username}",
    "text": "${text}",
    "icon_emoji":"${iconEmoji}"
  }`
  const param = {
    headers: {
      'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8',
    }
  }

  try {
    const res = await axios.post(path, data, param)
    console.log(res.data)
  } catch (err) {
    console.log(err)
  }
}

(async function () {
  await slack('xxxxxx', '#test', 'テストマン', 'テストコメント', ':memo:')
  console.log('slackにメッセージを送信しました。')
}())

実行

nodeコマンドでtest.jsを実行する

node test

出力結果

ok
slackにメッセージを送信しました。

参考文献

この記事は以下の情報を参考にして執筆しました。

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

async/awaitでシンプルにsetTimeoutする

async/awaitを使用するときに、setTimeoutPromiseを返す関数を作ります。

delayメソッド

const delay = ms => new Promise(resolve => setTimeout(resolve, ms));

※この後の使い方を続けて記述する場合、↑行末のセミコロンを省略すると使えません。

使い方

awaitdelayメソッドを使い、引数にはミリ秒単位で時間を入れる、その間後続の処理は行われません。

(async function() {
  await delay(3000)
  console.log('3秒経ちました。')
}())

出力結果

3秒経ちました。

3秒後に「3秒経ちました。」と出力されました。

参考文献

この記事は以下の情報を参考にして執筆しました。

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

【JavaScript】JSONを検索して、特定のデータを取り出す方法

まずはJSONデータを用意

とりあえずこんな感じで用意しました。

const JSONDATA = [
  {
    id: "aaa",
    name: "apple"
  },
  {
    id: "bbb",
    name: "orange"
  },
  {
    id: "ccc",
    name: "grape"
  }
];

idを指定してオレンジを取り出す!

「findIndex」を使って何番目かを確認し(0はじまり)、その番号を指定してJSONデータを返します。

const getFruitById = id => {
    const fruitIndex = JSONDATA.findIndex(data => data.id === id);
    return JSONDATA[fruitIndex];
};

const orange =  getFruitById("bbb");
console.log(orange.name); // display orange

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