20190228のJavaScriptに関する記事は19件です。

「Debugger for Chrome」で launch.json の file の書き方

「Debugger for Chrome」で launch.json の file の書き方

誰のため?

Visual Studio Code で HTML 内に Javascript のコードを書いて、その場でデバッグ実行してみようと Debugger for Chrome プラグインを入れて F5 キーを押してみたけど、うまくいかず「いや、だから、index.html じゃなくて、いま開いている編集中のこのHTMLのコードをデバッグ実行したいんだってば!!」って思ったひと向け。

ちなみに、Debugger for Chrome は超絶便利なので、Visual Studio Codeを入れたら絶対入れるべきおすすめプラグイン

答えは ${file}

キモはこれ -> "file": "${file}"

launch.json にこれを書くだけで VSCode が開いているHTMLファイルをChromeが開くようになる。もちろんデバッグもできるようになる。

最初から、そう書いておいてくれれば百倍助かるのにね。

launch.json
{
    // IntelliSense を使用して利用可能な属性を学べます。
    // 既存の属性の説明をホバーして表示します。
    // 詳細情報は次を確認してください: https://go.microsoft.com/fwlink/?linkid=830387
    "version": "0.2.0",
    "configurations": [
        {
            "type": "chrome",
            "request": "launch",
            "name": "Launch Chrome",
            "file": "${file}"
        }
    ]
}

たったそれだけのことなのに、ググってもなかなか出てこないんだよね。

これで、Javascript を高速デバッグできますね。どぉ?できた??

参考:

${file} 以外に定義されている変数はこちら
https://code.visualstudio.com/docs/editor/variables-reference

The following predefined variables are supported:

${workspaceFolder} - the path of the folder opened in VS Code
${workspaceFolderBasename} - the name of the folder opened in VS Code without any slashes (/)
${file} - the current opened file
${relativeFile} - the current opened file relative to workspaceFolder
${fileBasename} - the current opened file's basename
${fileBasenameNoExtension} - the current opened file's basename with no file extension
${fileDirname} - the current opened file's dirname
${fileExtname} - the current opened file's extension
${cwd} - the task runner's current working directory on startup
${lineNumber} - the current selected line number in the active file
${selectedText} - the current selected text in the active file
${execPath} - the path to the running VS Code executable

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

オリジナルKdB(科目検索)を作ってみよう -番外1- FaaS下準備編

これまでの記事

スクリーンショット 2019-02-22 16.11.47.png

この記事を読む前に

ある特定の人にしかわからない単語が出現する可能性が高いです。あらかじめご了承ください。

この記事での開発環境

  • MacOS 10.14.3
  • Visual Studio Code 1.31.1
  • Node.js LTS 10.15.1

はじめに

「オリジナルKdB(科目検索)を作ってみよう」の番外編です。これまではExpress.jsは使わず、サーバレスなシステムを作っていきましょう。シリーズでやっていたようにExpress.jsでエンヤコラはやらずに、関数を作るだけで簡単にサービスを作ることができます。

FaaS について

IaaS,BaaS,PaaS,SaaSなどに連なるサービスの1つがFaaS(Function as a Service)です。関数のみを記述するだけで良く、サーバ周りの記述を省略できる画期的なサービスです。

「サーバ周りに関するコードを書かない → サーバを用意する必要がない」ことからサーバレスアーキテクチャと呼ばれます(縮めて「サーバレス」と呼ばれることが多いです)。

  • lambda関数を用意する。
  • FaaSにアップロードする。

たった2ステップで簡単です。しかも、サーバを持たないのでDDoS攻撃によってサーバが落ちることがありません。データベースに直接接続していないため「サーバに侵入されて個人情報が...!?」というケースもありません。しかもサーバを24時間365日稼働しているわけではありません。リクエストが来た時だけ稼動するのでコストを抑えることができます。

簡単・安全・安いがFaaSのウリです。

FaaSを提供しているサービス

FaaSを提供しているサービスはいくつかあります。

AWS lambda

スクリーンショット 2019-02-28 22.13.48.png

AWS(Amazon Web Service)で提供されているFaaSです。
さすがAWSというだけあって、毎月100万リクエスト、400,000 GB-秒まで無料とめちゃめちゃ太っ腹です。Node.js以外にPython, C#(.NET Core), Go, Java, Rubyと多様な言語に対応しています。まず始めるならオススメしたいFaaSと言えます。

また、AWSが提供する他のサービスとの連携に優れており「S3(AWSの提供するクラウドストレージ)にファイルをアップロードしたら自動的に圧縮する」ような処理を簡単に組み立てることができます。

Google Cloud Functions

スクリーンショット 2019-02-28 22.27.18.png

GCP(Google Cloud Platform)で提供されているFaaSです。
こちらも200万リクエスト、計算時間100万秒まで無料と太っ腹。こちらはNode.js限定(Go, Pythonがベータ版)です。専用のライブラリを入れる必要がありますがlambda関数の書き方が簡潔であり、日本語のレファレンスが充実しています。

GCPの他のサービスと連携しやすいのも利点です。GCPのサービスは欲しいところに欲しい説明をくれるので、初心者から上級者まで使いこなせるのがいいですね。

IBM Cloud Functions

スクリーンショット 2019-02-28 22.40.37.png

IBM Cloud で提供されているFaaSです。
使ったことがないので料金体系がわかりませんが、見た感じとても安いです。何よりもNode10.XSwift4.X, PHP 7.X, Python3.Xと、新しいバージョンに対応しているのが素晴らしいです。実行環境で最新の機能が使えるのが最高です。

Zeit Now

スクリーンショット 2019-02-28 22.48.24.png

爆速デプロイをウリにしているFaaSです。料金体系がわかりやすく、個人サイト程度の規模なら無料で使うことができます。課金をすれば激安定額なのに商業利用に耐えるスペックで利用できます。また、lambda関数をアップロード時に本番環境を想定したサーバに一旦保存されるので「本番にデプロイしたら不具合が起きた!!!」なんてことを事前に検証することができます。

とりあえず完全無料でFaaSを初めてみたいという方にはオススメです。

上記の他にもいくつもFaaSを提供しているサイトがあります。自分好みなサービスを見つけてがっつり使っていきましょう??

ところで今回すること → 下準備

Lambda系のサービスに共通する特徴にファイル入出力周りが安定しないことが挙げられます。そのため、これまで使っていたfsモジュールでのファイル読み込みは使わないように調整しましょう。

参考記事 → AWS Lambdaでファイル入出力をしてみる

module.exportsしたファイルはちゃんと読み込んでくれるので、CSVファイルに書かれている全ての情報をjavasctiptファイルに書き出しましょう。

まずは必要なパッケージをインストールします。

$ npm install iconv-lite csv 

そしたら、以下のようにdump.jsを作ります。

dump.js
const fs = require('fs');
const iconv = require('iconv-lite')
const parse = require('csv').parse;

// CSVファイル(Shift_jis)を読み込んでパース
const dataGet = () => {
    const text = fs.readFileSync("kdb.csv")
    const ret = iconv.decode( Buffer.from(text), "Shift_JIS");
    const dataArray = []
    parse(ret, (err, data) => {
        if (err) console.log(err.message)
        else {
            data.forEach( (element) => {
                dataArray.push(element)
            });
        }
    });
    return dataArray
}

// 配列をもらってJSON化
const dataToJson = async (dataArray) => {
    const dataJson = { subjects: [] }
    dataArray.forEach( (element) => {
        dataJson.subjects.push( 
            {
                id: element[0],
                name: element[1],
                lessonType: element[2],
                credit: element[3],
                level: element[4],
                semester: element[5],
                period: element[6],
                place: element[7],
                teachers: element[8],
                summary: element[9],
                remarks: element[10],
                otherCourseStatus: element[11],
                otherCourseInfo: element[12],
                engName: element[13],
                engId: element[14],
                searchOption: element[15],
                timestamp: element[16],
            }
        )
    })
    return dataJson
}

// 即時関数でdata.jsを生成
(async () => {
    const data = await dataGet()
    const json = await dataToJson(data)
    const myJs = `const json = ${JSON.stringify(json)};
module.exports = json;`
    fs.writeFileSync("data.js", myJs)
})()

※async/awaitについて説明してると記事が爆発的に大きくなってしまうので割愛します。
async/awaitについての参考サイト(Promiseと一緒に覚えると楽です)

実行して、新しくdata.jsが作られていることを確認しましょう。

$ node dump.js
$ ls
dump.js               kdb.csv         package.json
package-lock.json     node_modules    data.js

data.jsの中身をみればわかりますが、kdb.csvの情報が全て書き出されていることがわかります。もしうまく書き出せていなかったら、ごめんなさい...コメントにお願いします。

とりあえず今回はこの辺で

下準備だけで内容のない記事となってしまいましたが、次回からがっつりFaaSを使っていきますので許してください。
ちなみに、AWSとGCPの2つを触る予定です。

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

Vue.jsでグラデーションのアニメーション表示をしよう!Granim.js

Granim.js

Granim.jsはグラデーションをアニメーション表示させることができるJavaScriptライブラリです。
これを使うと、リッチなWebサイトを作ることができます!

どのようにアニメーション表示されるかは公式サイトのトップページExamplesをご覧ください。
Screenshot_2019-02-28 20.44.37_XuGUDd.png

このGranim.jsをVue.jsのアプリケーションで使ってみます。

手順

1.Gramin.jsのインストール

npm install granim

2.コンポーネントの作成

granim.vue
<template>
  <div>
    <canvas id="granim-canvas"></canvas>
  </div>
</template>

<script>
import Granim from 'granim'

export default {
  name: 'granim',
  data () {
    return {
      GObj: Object
    }
  },
  mounted () {
    this.GObj = new Granim({
      element: '#granim-canvas',
      name: 'granim',
      opacity: [1, 1],
      states: {
        'default-state': {
          gradients: [
             ['#29323c', '#485563'],
             ['#FF6B6B', '#556270'],
             ['#80d3fe', '#7ea0c4'],
             ['#f0ab51', '#eceba3']
          ]
        }
      }
    })
  }
}
</script>

<style scoped>
#granim-canvas {
  width: 100vw;
  height: 100vh;
}
</style>

キモはコンポーネントのmountedライフサイクルフックでGranimをnewするところです。
mounted()に記述するコードは公式サイトの通りに記述すればOKです。
newするときのオプションでスピードや色の指定など様々な表現ができます。

※上のサンプルコードではESLintのエラー回避のためにdataにnewしたGranimのインスタンスを代入しています。

3.完成!

ezgif.com-video-to-gif (2).gif

バリエーション

Granim.jsを使うとただのグラデーションだけではなく、画像と組み合わせたり、文字に対してグラデーションのアニメーションをつけることができます。公式サイトにやり方が載っています。
Screenshot_2019-02-28 20.55.56_RaImf3.png
Screenshot_2019-02-28 20.56.03_dPpNVJ.png

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

JavaScript オブジェクトの分割代入 オブジェクトの異なる名前のプロパティへ代入する

オブジェクトの分割代入で名前を変えて変数に代入できるが、
オブジェクトのプロパティに名前を変えて代入できるのだろうか。

変数に代入はもちろんできる。

var o = {p: 42, q: true, r: 'hoge'};

var {p: foo, q: bar, r: baz} = o; 
console.log(foo); // 42 
console.log(bar); // true  
console.log(baz); // 'hoge'  

オブジェクトの名前の違うプロパティに代入はどうだ。

var o = {p: 42, q: true, r: 'hoge'};

var o2 = {};
({p: o2.pp, q: o2.qq, r: o2.rr} = o);
console.log(o2); // {pp: 42, qq: true, rr: "hoge"}

できた!
けど、1つずつ代入する方が読みすい、かな。

var o2 = {};
o2.pp = o.p;
o2.qq = o.q;
o2.rr = o.r;

参考
https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Operators/Destructuring_assignment

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

住所に含まれる色んな横棒をぜんぶ半角ハイフンに変える

(追記)
@luna-mrst さんから後半のfor文は正規表現にて簡略化できるとご指摘いただきました。
ありがとうございます。来週からの業務が捗ります(大袈裟でなく)。

以下コメント引用です。

yokobou2hyphen.js
function yokobou(str) {
  const list = ["\uFF0D","\uFE63","\u2212","\u2010",
              "\u2043","\u2011","\u2012","\u2013","\u2014",
              "\ufe58","\u2015","\u23AF","\u23E4","\u02D7",
              "\u2796","\u208B","\u30FC","\uFF70"];  

  const reg = new RegExp(`(?<=\\d)[${list.join('')}](?=\\d)`, 'g');
  return str.replace(reg, '-');
}

(追記ここまで)

最近グーグルスプレッドシートで住所一覧を渡されてごちゃごちゃ何かすることが多いのですが、書き方が統一されていないのでいつもキレ気味の私です。

この「住所のフォーマットを統一する」シリーズは数回続く予定です。

特に難しいことはしません。

yokobou2hyphen.js
// 横棒っぽいものを全てハイフンに置き換える
function yokobou(str){
  //--‐―ーー─━ ← 横棒の例

  // 横棒のリスト
  var list = ["\uFF0D","\uFE63","\u2212","\u2010",
              "\u2043","\u2011","\u2012","\u2013","\u2014",
              "\ufe58","\u2015","\u23AF","\u23E4","\ux2D7",
              "\u2796","\u208B","\u30FC","\uFF70"];

  for(var i=0;i<list.length;i++){
    // 数字と数字に挟まれた横棒を探す
    var reg = new RegExp("\\d" + list[i] + "\\d","g"); // reg = /\dー\d/g
    var match = str.match(reg);
    if(match){
      for(var j=0;j<match.length;j++){
        var oldStr = match[j]; // ex) 5ー2
        var newStr = match[j].replace(list[i],"-"); // ex) 5-2
        str = str.replace(oldStr,newStr); // 該当箇所を置き換える
      }
    }
  }
  return str;
}

// 実行例
  var add = "宮城県仙台市横浜区1ー2―3—405";
  var add2 = yokobou(add);
  // add2 = "宮城県仙台市横浜区1-2-3-405";

list で挙げたすべての横棒について、「数字(横棒)数字」という並びを正規表現で探し、「数字(ハイフン)数字」に置き換えています。
正規表現のところで g オプションを付けているので、該当する箇所全てが配列で返ってきます。

横棒のリストはこちらのサイト
http://www13.plala.or.jp/bigdata/yokobou.html
を参考にしました。
他にも思いついたら list に適宜付け加えてください。
例えば、listに"の"を追加すると、「1の2」→「1-2」ができます。

しかしもっと頭の良い根本的な解決方法は、ハイフン以外の横棒は使用禁止という規則を周知することじゃないかなと思います(怒)

(つづく)

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

【SharePoint2010】クリックして手軽に更新できる座席表を作成してみました。

作ったわけ

部署単位ではかたまって座っているんですが、席替えが頻繁で、
あの部署どこらへんにいるんだっけ?というのが頻繁に変わるため
更新がパパッとクリックしてできるような座席表があったらいいなあと……。

画面イメージ

フロアにぐるりと島があるような感じです。
とりあえず10島、1島の最大座席数は16席。
丸く囲むと真ん中が空いちゃってもったいないので、部署ごとの座席数を表示するようにしてみました。
画面イメージ.png

座席状況はSharePointリストに保存します。

ここの例では、このリストはlistZasekiSampleという名前にしています。
既存のタイトル列に島名を3文字で表記したもの(この例でいうとS01,S02など)が入ります。
za~zpまで16列作成します。全部1行テキストです。
列の名前がza,zb…とかである理由は、なんでかわからないんですがSharePointの列名に数字とかを混ぜると勝手にエンコードされたような内部名になっちゃうことが頻発するので、半角英字のみ使うようにしています。
なんで勝手にエスケープシーケンスみたいなのがついたりしちゃうんでしょう……数字も半角なのに……

1行1島。なので、島の増減は、このリストの行を増減して対応します。
リストを読んだり書いたりするのは SPServices を使っています。

書いたコード

CSS

<style>
    .tableBorder1 {
        border-collapse: collapse;
    }

    .tableMigiYose {
        margin-left: auto;
        margin-right: 0;
    }

    .tableHidariYose {
        margin-left: 0;
        margin-right: auto;
    }

    .tableUe {
        margin-bottom: 1em;
        padding-bottom: 1em;
        vertical-align: bottom;
    }

    .tableShita {
        margin-top: 1em;
        padding-top: 1em;
        vertical-align: top;
    }

    .tableTate {
        width: 65em;
        padding-top: 1em;
        padding-bottom: 1em;
    }

    .tableBorder1,
    .tableBorder1 td,
    .tableBorder1 th {
        border: 1px solid black;
        padding: 0.5em;
    }

    .tableBorder1 td,
    .tableBorder1 th {
        text-align: center;
    }

    .tableBorder1 .simaName {
        font-weight: bold;
        font-size: 2em;
    }

    .tbltd {
        width: 8em;
        height: 5em;
        text-align: center;
        vertical-align: middle;
    }

    .zaseki {
        width: 7em;
        height: 4em;
        background-color: white;
    }

    .zaseki.color {
        background-color: white;
    }

    .zaseki.color部署01 {
        background-color: cyan;
    }

    .zaseki.color部署02 {
        background-color: pink;
    }

    .zaseki.color部署03 {
        background-color: yellow;
    }

    .zaseki.color部署04 {
        background-color: palegreen;
    }

    .zaseki.color部署05 {
        background-color: violet;
    }

    .zaseki.color部署06 {
        background-color: darkkhaki;
    }

    .zaseki.color部署07 {
        background-color: orange;
    }

    .bgColorCenter {
        background-color: lightsteelblue;
        border: 0px;
        border-collapse: separate;
        border-spacing: 0px;
        padding: 3em;
    }

    .honbuCenter {
        border: seagreen 5px ridge;
        padding: 3em;
        margin: 8em;
        width: 30em;
    }
</style>

部署選択

座席をクリックすると、ここで選択した部署名が入ります。

<div style="overflow:auto;">
    <div>
        <select id="busho">
            <option value="部署01">部署01</option>
            <option value="部署02">部署02</option>
            <option value="部署03">部署03</option>
            <option value="部署04">部署04</option>
            <option value="部署05">部署05</option>
            <option value="部署06">部署06</option>
            <option value="部署07">部署07</option>
        </select>
    </div>
</div>

座席表

フロアレイアウトが変わるごとにここを書き直すのが一番めんどくさいかも……

<table>
    <tr>
        <td colspan="4" align="center">
            <table>
                <tr class="tableUe">
                    <td>
                        <table id="S01" class="tableBorder1">
                            <tbody>
                                <tr>
                                    <td class="tbltd"><input class="zaseki color空" id="S01-01" type="button" value="空" /></td>
                                    <td class="tbltd"><input class="zaseki color空" id="S01-02" type="button" value="空" /></td>
                                </tr>
                                <tr>
                                    <td class="tbltd"><input class="zaseki color空" id="S01-03" type="button" value="空" /></td>
                                    <td class="tbltd"><input class="zaseki color空" id="S01-04" type="button" value="空" /></td>
                                </tr>
                                <tr>
                                    <td class="tbltd"><input class="zaseki color空" id="S01-05" type="button" value="空" /></td>
                                    <td class="tbltd"><input class="zaseki color空" id="S01-06" type="button" value="空" /></td>
                                </tr>
                                <tr>
                                    <td class="tbltd"><input class="zaseki color空" id="S01-07" type="button" value="空" /></td>
                                    <td class="tbltd"><input class="zaseki color空" id="S01-08" type="button" value="空" /></td>
                                </tr>
                                <tr>
                                    <td class="tbltd" colspan="2"><span class="simaName">S-1</span><br><input class="allo" id="S01-allo" type="button" value="全部埋める" /><br/><input class="allx" id="S01-allx" type="button" value="全部を空に" /></td>
                                </tr>
                            </tbody>
                        </table>
                    </td>
                    <td>
                        <table id="S02" class="tableBorder1">
                            <tbody>
                                <tr>
                                    <td class="tbltd"><input class="zaseki color空" id="S02-01" type="button" value="空" /></td>
                                    <td class="tbltd"><input class="zaseki color空" id="S02-02" type="button" value="空" /></td>
                                </tr>
                                <tr>
                                    <td class="tbltd"><input class="zaseki color空" id="S02-03" type="button" value="空" /></td>
                                    <td class="tbltd"><input class="zaseki color空" id="S02-04" type="button" value="空" /></td>
                                </tr>
                                <tr>
                                    <td class="tbltd"><input class="zaseki color空" id="S02-05" type="button" value="空" /></td>
                                    <td class="tbltd"><input class="zaseki color空" id="S02-06" type="button" value="空" /></td>
                                </tr>
                                <tr>
                                    <td class="tbltd"><input class="zaseki color空" id="S02-07" type="button" value="空" /></td>
                                    <td class="tbltd"><input class="zaseki color空" id="S02-08" type="button" value="空" /></td>
                                </tr>
                                <tr>
                                    <td class="tbltd" colspan="2"><span class="simaName">S-2</span><br><input class="allo" id="S02-allo" type="button" value="全部埋める" /><br/><input class="allx" id="S02-allx" type="button" value="全部を空に" /></td>
                                </tr>
                            </tbody>
                        </table>
                    </td>
                    <td>
                        <table id="S03" class="tableBorder1">
                            <tbody>
                                <tr>
                                    <td class="tbltd"><input class="zaseki color空" id="S03-01" type="button" value="空" /></td>
                                    <td class="tbltd"><input class="zaseki color空" id="S03-02" type="button" value="空" /></td>
                                </tr>
                                <tr>
                                    <td class="tbltd"><input class="zaseki color空" id="S03-03" type="button" value="空" /></td>
                                    <td class="tbltd"><input class="zaseki color空" id="S03-04" type="button" value="空" /></td>
                                </tr>
                                <tr>
                                    <td class="tbltd"><input class="zaseki color空" id="S03-05" type="button" value="空" /></td>
                                    <td class="tbltd"><input class="zaseki color空" id="S03-06" type="button" value="空" /></td>
                                </tr>
                                <tr>
                                    <td class="tbltd"><input class="zaseki color空" id="S03-07" type="button" value="空" /></td>
                                    <td class="tbltd"><input class="zaseki color空" id="S03-08" type="button" value="空" /></td>
                                </tr>
                                <tr>
                                    <td class="tbltd"><input class="zaseki color空" id="S03-09" type="button" value="空" /></td>
                                    <td class="tbltd"><input class="zaseki color空" id="S03-10" type="button" value="空" /></td>
                                </tr>
                                <tr>
                                    <td class="tbltd"><input class="zaseki color空" id="S03-11" type="button" value="空" /></td>
                                    <td class="tbltd"><input class="zaseki color空" id="S03-12" type="button" value="空" /></td>
                                </tr>
                                <tr>
                                    <td class="tbltd" colspan="2"><span class="simaName">S-3</span><br><input class="allo" id="S03-allo" type="button" value="全部埋める" /><br/><input class="allx" id="S03-allx" type="button" value="全部を空に" /></td>
                                </tr>
                            </tbody>
                        </table>
                    </td>
                </tr>
            </table>
        </td>
    </tr>
    <tr>
        <td class="tableTate">
            <table id="S04" class="tableBorder1 tableHidariYose">
                <tbody>
                    <tr>
                        <td class="tbltd"><input class="zaseki color空" id="S04-02" type="button" value="空" /></td>
                        <td class="tbltd"><input class="zaseki color空" id="S04-04" type="button" value="空" /></td>
                        <td class="tbltd"><input class="zaseki color空" id="S04-06" type="button" value="空" /></td>
                        <td class="tbltd"><input class="zaseki color空" id="S04-08" type="button" value="空" /></td>
                        <td class="tbltd"><input class="zaseki color空" id="S04-10" type="button" value="空" /></td>
                        <td class="tbltd"><input class="zaseki color空" id="S04-12" type="button" value="空" /></td>
                        <td class="tbltd"><input class="zaseki color空" id="S04-14" type="button" value="空" /></td>
                        <td class="tbltd"><input class="zaseki color空" id="S04-16" type="button" value="空" /></td>
                        <td class="tbltd" rowspan="2"><span class="simaName">S-4</span><br><input class="allo" id="S04-allo" type="button" value="全部埋める" /><br/><input class="allx" id="S04-allx" type="button" value="全部を空に" /></td>
                    </tr>
                    <tr>
                        <td class="tbltd"><input class="zaseki color空" id="S04-01" type="button" value="空" /></td>
                        <td class="tbltd"><input class="zaseki color空" id="S04-03" type="button" value="空" /></td>
                        <td class="tbltd"><input class="zaseki color空" id="S04-05" type="button" value="空" /></td>
                        <td class="tbltd"><input class="zaseki color空" id="S04-07" type="button" value="空" /></td>
                        <td class="tbltd"><input class="zaseki color空" id="S04-09" type="button" value="空" /></td>
                        <td class="tbltd"><input class="zaseki color空" id="S04-11" type="button" value="空" /></td>
                        <td class="tbltd"><input class="zaseki color空" id="S04-13" type="button" value="空" /></td>
                        <td class="tbltd"><input class="zaseki color空" id="S04-15" type="button" value="空" /></td>
                    </tr>
                </tbody>
            </table>
        </td>
        <td colspan="2" rowspan="3" style="vertical-align: top; position: relative;" class="bgColorCenter">

            <div class="honbuCenter">
                <h2>各部署座席数</h2>
                <div>合計:<span id="numAll"></span></div>
                <div>部署01:<span id="numB01"></span></div>
                <div>部署02:<span id="numB02"></span></div>
                <div>部署03:<span id="numB03"></span></div>
                <div>部署04:<span id="numB04"></span></div>
                <div>部署05:<span id="numB05"></span></div>
                <div>部署06:<span id="numB06"></span></div>
                <div>部署07:<span id="numB07"></span></div>
            </div>
            <div style="display:none">
                <div class="sima" id="01"></div>
                <div class="sima" id="02"></div>
                <div class="sima" id="03"></div>
                <div class="sima" id="04"></div>
                <div class="sima" id="05"></div>
                <div class="sima" id="06"></div>
                <div class="sima" id="07"></div>
                <div class="sima" id="08"></div>
                <div class="sima" id="09"></div>
                <div class="sima" id="10"></div>
                <div class="sima" id="11"></div>
                <div class="sima" id="12"></div>
                <div class="sima" id="13"></div>
                <div class="sima" id="14"></div>
                <div class="sima" id="15"></div>
                <div class="sima" id="16"></div>
                <div class="sima" id="iid">S01</div>
            </div>
        </td>
        <td class="tableTate">
            <table id="S05" class="tableBorder1 tableMigiYose">
                <tbody>
                    <tr>
                        <td class="tbltd" rowspan="2"><span class="simaName">S-5</span><br><input class="allo" id="S05-allo" type="button" value="全部埋める" /><br/><input class="allx" id="S05-allx" type="button" value="全部を空に" /></td>
                        <td class="tbltd"><input class="zaseki color空" id="S05-02" type="button" value="空" /></td>
                        <td class="tbltd"><input class="zaseki color空" id="S05-04" type="button" value="空" /></td>
                        <td class="tbltd"><input class="zaseki color空" id="S05-06" type="button" value="空" /></td>
                        <td class="tbltd"><input class="zaseki color空" id="S05-08" type="button" value="空" /></td>
                        <td class="tbltd"><input class="zaseki color空" id="S05-10" type="button" value="空" /></td>
                        <td class="tbltd"><input class="zaseki color空" id="S05-12" type="button" value="空" /></td>
                        <td class="tbltd"><input class="zaseki color空" id="S05-14" type="button" value="空" /></td>
                        <td class="tbltd"><input class="zaseki color空" id="S05-16" type="button" value="空" /></td>
                    </tr>
                    <tr>
                        <td class="tbltd"><input class="zaseki color空" id="S05-01" type="button" value="空" /></td>
                        <td class="tbltd"><input class="zaseki color空" id="S05-03" type="button" value="空" /></td>
                        <td class="tbltd"><input class="zaseki color空" id="S05-05" type="button" value="空" /></td>
                        <td class="tbltd"><input class="zaseki color空" id="S05-07" type="button" value="空" /></td>
                        <td class="tbltd"><input class="zaseki color空" id="S05-09" type="button" value="空" /></td>
                        <td class="tbltd"><input class="zaseki color空" id="S05-11" type="button" value="空" /></td>
                        <td class="tbltd"><input class="zaseki color空" id="S05-13" type="button" value="空" /></td>
                        <td class="tbltd"><input class="zaseki color空" id="S05-15" type="button" value="空" /></td>
                    </tr>
                </tbody>
            </table>
        </td>
    </tr>
    <tr></tr>
    <td class="tableTate">
        <table id="S06" class="tableBorder1 tableHidariYose">
            <tbody>
                <tr>
                    <td class="tbltd"><input class="zaseki color空" id="S06-15" type="button" value="空" /></td>
                    <td class="tbltd"><input class="zaseki color空" id="S06-13" type="button" value="空" /></td>
                    <td class="tbltd"><input class="zaseki color空" id="S06-11" type="button" value="空" /></td>
                    <td class="tbltd"><input class="zaseki color空" id="S06-09" type="button" value="空" /></td>
                    <td class="tbltd"><input class="zaseki color空" id="S06-07" type="button" value="空" /></td>
                    <td class="tbltd"><input class="zaseki color空" id="S06-05" type="button" value="空" /></td>
                    <td class="tbltd"><input class="zaseki color空" id="S06-03" type="button" value="空" /></td>
                    <td class="tbltd"><input class="zaseki color空" id="S06-01" type="button" value="空" /></td>
                    <td class="tbltd" rowspan="2"><span class="simaName">S-6</span><br><input class="allo" id="S06-allo" type="button" value="全部埋める" /><br/><input class="allx" id="S06-allx" type="button" value="全部を空に" /></td>
                </tr>
                <tr>
                    <td class="tbltd"><input class="zaseki color空" id="S06-16" type="button" value="空" /></td>
                    <td class="tbltd"><input class="zaseki color空" id="S06-14" type="button" value="空" /></td>
                    <td class="tbltd"><input class="zaseki color空" id="S06-12" type="button" value="空" /></td>
                    <td class="tbltd"><input class="zaseki color空" id="S06-10" type="button" value="空" /></td>
                    <td class="tbltd"><input class="zaseki color空" id="S06-08" type="button" value="空" /></td>
                    <td class="tbltd"><input class="zaseki color空" id="S06-06" type="button" value="空" /></td>
                    <td class="tbltd"><input class="zaseki color空" id="S06-04" type="button" value="空" /></td>
                    <td class="tbltd"><input class="zaseki color空" id="S06-02" type="button" value="空" /></td>
                </tr>
            </tbody>
        </table>
    </td>
    <td class="tableTate">
        <table id="S07" class="tableBorder1 tableMigiYose">
            <tbody>
                <tr>
                    <td class="tbltd" rowspan="2"><span class="simaName">S-7</span><br><input class="allo" id="S07-allo" type="button" value="全部埋める" /><br/><input class="allx" id="S07-allx" type="button" value="全部を空に" /></td>
                    <td class="tbltd"><input class="zaseki color空" id="S07-02" type="button" value="空" /></td>
                    <td class="tbltd"><input class="zaseki color空" id="S07-04" type="button" value="空" /></td>
                    <td class="tbltd"><input class="zaseki color空" id="S07-06" type="button" value="空" /></td>
                    <td class="tbltd"><input class="zaseki color空" id="S07-08" type="button" value="空" /></td>
                    <td class="tbltd"><input class="zaseki color空" id="S07-10" type="button" value="空" /></td>
                    <td class="tbltd"><input class="zaseki color空" id="S07-12" type="button" value="空" /></td>
                    <td class="tbltd"><input class="zaseki color空" id="S07-14" type="button" value="空" /></td>
                    <td class="tbltd"><input class="zaseki color空" id="S07-16" type="button" value="空" /></td>
                </tr>
                <tr>
                    <td class="tbltd"><input class="zaseki color空" id="S07-01" type="button" value="空" /></td>
                    <td class="tbltd"><input class="zaseki color空" id="S07-03" type="button" value="空" /></td>
                    <td class="tbltd"><input class="zaseki color空" id="S07-05" type="button" value="空" /></td>
                    <td class="tbltd"><input class="zaseki color空" id="S07-07" type="button" value="空" /></td>
                    <td class="tbltd"><input class="zaseki color空" id="S07-09" type="button" value="空" /></td>
                    <td class="tbltd"><input class="zaseki color空" id="S07-11" type="button" value="空" /></td>
                    <td class="tbltd"><input class="zaseki color空" id="S07-13" type="button" value="空" /></td>
                    <td class="tbltd"><input class="zaseki color空" id="S07-15" type="button" value="空" /></td>
                </tr>
            </tbody>
        </table>
    </td>
    </tr>
    <tr>
        <td colspan="4" align="center">
            <table>
                <tr class="tableShita">
                    <td>
                        <table id="S08" class="tableBorder1">
                            <tbody>
                                <tr>
                                    <td class="tbltd" colspan="2"><span class="simaName">S-8</span><br><input class="allo" id="S08-allo" type="button" value="全部埋める" /><br/><input class="allx" id="S08-allx" type="button" value="全部を空に" /></td>
                                </tr>
                                <tr>
                                    <td class="tbltd"><input class="zaseki color空" id="S08-08" type="button" value="空" /></td>
                                    <td class="tbltd"><input class="zaseki color空" id="S08-07" type="button" value="空" /></td>
                                </tr>
                                <tr>
                                    <td class="tbltd"><input class="zaseki color空" id="S08-06" type="button" value="空" /></td>
                                    <td class="tbltd"><input class="zaseki color空" id="S08-05" type="button" value="空" /></td>
                                </tr>
                                <tr>
                                    <td class="tbltd"><input class="zaseki color空" id="S08-04" type="button" value="空" /></td>
                                    <td class="tbltd"><input class="zaseki color空" id="S08-03" type="button" value="空" /></td>
                                </tr>
                                <tr>
                                    <td class="tbltd"><input class="zaseki color空" id="S08-02" type="button" value="空" /></td>
                                    <td class="tbltd"><input class="zaseki color空" id="S08-01" type="button" value="空" /></td>
                                </tr>
                            </tbody>
                        </table>
                    </td>
                    <td>
                        <table id="S09" class="tableBorder1">
                            <tbody>
                                <tr>
                                    <td class="tbltd" colspan="2"><span class="simaName">S-9</span><br><input class="allo" id="S09-allo" type="button" value="全部埋める" /><br/><input class="allx" id="S09-allx" type="button" value="全部を空に" /></td>
                                </tr>
                                <tr>
                                    <td class="tbltd"><input class="zaseki color空" id="S09-16" type="button" value="空" /></td>
                                    <td class="tbltd"><input class="zaseki color空" id="S09-15" type="button" value="空" /></td>
                                </tr>
                                <tr>
                                    <td class="tbltd"><input class="zaseki color空" id="S09-14" type="button" value="空" /></td>
                                    <td class="tbltd"><input class="zaseki color空" id="S09-13" type="button" value="空" /></td>
                                </tr>
                                <tr>
                                    <td class="tbltd"><input class="zaseki color空" id="S09-12" type="button" value="空" /></td>
                                    <td class="tbltd"><input class="zaseki color空" id="S09-11" type="button" value="空" /></td>
                                </tr>
                                <tr>
                                    <td class="tbltd"><input class="zaseki color空" id="S09-10" type="button" value="空" /></td>
                                    <td class="tbltd"><input class="zaseki color空" id="S09-09" type="button" value="空" /></td>
                                </tr>
                                <tr>
                                    <td class="tbltd"><input class="zaseki color空" id="S09-08" type="button" value="空" /></td>
                                    <td class="tbltd"><input class="zaseki color空" id="S09-07" type="button" value="空" /></td>
                                </tr>
                                <tr>
                                    <td class="tbltd"><input class="zaseki color空" id="S09-06" type="button" value="空" /></td>
                                    <td class="tbltd"><input class="zaseki color空" id="S09-05" type="button" value="空" /></td>
                                </tr>
                                <tr>
                                    <td class="tbltd"><input class="zaseki color空" id="S09-04" type="button" value="空" /></td>
                                    <td class="tbltd"><input class="zaseki color空" id="S09-03" type="button" value="空" /></td>
                                </tr>
                                <tr>
                                    <td class="tbltd"><input class="zaseki color空" id="S09-02" type="button" value="空" /></td>
                                    <td class="tbltd"><input class="zaseki color空" id="S09-01" type="button" value="空" /></td>
                                </tr>
                            </tbody>
                        </table>
                    </td>
                    <td>
                        <table id="S10" class="tableBorder1">
                            <tbody>
                                <tr>
                                    <td class="tbltd" colspan="2"><span class="simaName">S-10</span><br><input class="allo" id="S10-allo" type="button" value="全部埋める" /><br/><input class="allx" id="S10-allx" type="button" value="全部を空に" /></td>
                                </tr>
                                <tr>
                                    <td class="tbltd"><input class="zaseki color空" id="S10-08" type="button" value="空" /></td>
                                    <td class="tbltd"><input class="zaseki color空" id="S10-07" type="button" value="空" /></td>
                                </tr>
                                <tr>
                                    <td class="tbltd"><input class="zaseki color空" id="S10-06" type="button" value="空" /></td>
                                    <td class="tbltd"><input class="zaseki color空" id="S10-05" type="button" value="空" /></td>
                                </tr>
                                <tr>
                                    <td class="tbltd"><input class="zaseki color空" id="S10-04" type="button" value="空" /></td>
                                    <td class="tbltd"><input class="zaseki color空" id="S10-03" type="button" value="空" /></td>
                                </tr>
                                <tr>
                                    <td class="tbltd"><input class="zaseki color空" id="S10-02" type="button" value="空" /></td>
                                    <td class="tbltd"><input class="zaseki color空" id="S10-01" type="button" value="空" /></td>
                                </tr>
                            </tbody>
                        </table>
                    </td>
                </tr>
            </table>
        </td>
    </tr>
</table>

リストから読んで画面に展開する

<script src="http://cdnjs.cloudflare.com/ajax/libs/jquery.SPServices/2014.01/jquery.SPServices.min.js" type="text/javascript"></script>
<script type="text/javascript">
(function (){

    var itemId;
    var a;
    var b;
    var c;
    var d;
    var e;
    var f;
    var g;
    var h;
    var i;
    var j;
    var k;
    var l;
    var m;
    var n;
    var o;
    var p;

    $().SPServices({
        operation: "GetListItems",
        async: false,
        listName: 'listZasekiSample',
        completefunc: function (xData, Status) {
            $(xData.responseXML).SPFilterNode("z:row").each(function () {
                itemId= $(this).attr("ows_Title");
                a = $(this).attr("ows_za");
                b = $(this).attr("ows_zb");
                c = $(this).attr("ows_zc");
                d = $(this).attr("ows_zd");
                e = $(this).attr("ows_ze");
                f = $(this).attr("ows_zf");
                g = $(this).attr("ows_zg");
                h = $(this).attr("ows_zh");
                i = $(this).attr("ows_zi");
                j = $(this).attr("ows_zj");
                k = $(this).attr("ows_zk");
                l = $(this).attr("ows_zl");
                m = $(this).attr("ows_zm");
                n = $(this).attr("ows_zn");
                o= $(this).attr("ows_zo");
                p = $(this).attr("ows_zp");
                $("#01").text(a);
                $("#02").text(b);
                $("#03").text(c);
                $("#04").text(d);
                $("#05").text(e);
                $("#06").text(f);
                $("#07").text(g);
                $("#08").text(h);
                $("#09").text(i);
                $("#10").text(j);
                $("#11").text(k);
                $("#12").text(l);
                $("#13").text(m);
                $("#14").text(n);
                $("#15").text(o);
                $("#16").text(p);
                $("#iid").text(itemId);
                $("#"+itemId+"-01").val(a).addClass('color'+a);
                $("#"+itemId+"-02").val(b).addClass('color'+b);
                $("#"+itemId+"-03").val(c).addClass('color'+c);
                $("#"+itemId+"-04").val(d).addClass('color'+d);
                $("#"+itemId+"-05").val(e).addClass('color'+e);
                $("#"+itemId+"-06").val(f).addClass('color'+f);
                $("#"+itemId+"-07").val(g).addClass('color'+g);
                $("#"+itemId+"-08").val(h).addClass('color'+h);
                $("#"+itemId+"-09").val(i).addClass('color'+i);
                $("#"+itemId+"-10").val(j).addClass('color'+j);
                $("#"+itemId+"-11").val(k).addClass('color'+k);
                $("#"+itemId+"-12").val(l).addClass('color'+l);
                $("#"+itemId+"-13").val(m).addClass('color'+m);
                $("#"+itemId+"-14").val(n).addClass('color'+n);
                $("#"+itemId+"-15").val(o).addClass('color'+o);
                $("#"+itemId+"-16").val(p).addClass('color'+p);
            });
        }
    });


})();
</script>

ボタンをクリックしたときに動作する(ボタンの表示を変更して、リストに書き戻す)

<script src="https://code.jquery.com/jquery-3.1.1.min.js" integrity="sha256-hVVnYaiADRTO2PzUGmuLJr8BLUSjGIZsDYGmIJLv2b8=" crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery.SPServices/2014.02/jquery.SPServices-2014.02.js" integrity="sha256-Jtnxf7StGlDFTa3A5i+RDBMWlBkpOPE9tF2ZW2xSoDI=" crossorigin="anonymous">
</script>

<script type="text/javascript">
    $(function() {
        countZaseki();
        var bushoCD = '部署01';
        var iid;
        var simaid;

        $('#busho').change(function() {
            bushoCD = $('#busho').val();
        });

        //全部埋める
        $('.allo').on('click', function() {
            simaid = $(this).attr('id').slice(0, 3);
            remColorClass(this);
            $('#' + simaid + ' .zaseki').val(bushoCD).removeClass('.allx').addClass('color' + bushoCD, '.allo');
            addColorClass(this);
        });

        //全部を空に
        $('.allx').on('click', function() {
            simaid = $(this).attr('id').slice(0, 3);
            remColorClass(this);
            $('#' + simaid + ' .zaseki').val('空').removeClass('.allo').addClass('color空', '.allx');
            addColorClass(this);
        });

        //座席個々をクリック
        $('.zaseki').on('click', function() {
            simaid = $(this).attr('id').slice(0, 3);
            remColorClass(this);
            if ($(this).val() == '空') {
                $(this).val(bushoCD);
            } else {
                $(this).val('空');
            }
            addColorClass(this);
        });

        $('.allo, .allx, .zaseki').on('click', function() {
            countZaseki();

            //当該の島を書き出し用テーブルに転記
            simaid = $(this).attr('id').slice(0, 3);
            $('#01').html($('#' + simaid + '-01').val());
            $('#02').html($('#' + simaid + '-02').val());
            $('#03').html($('#' + simaid + '-03').val());
            $('#04').html($('#' + simaid + '-04').val());
            $('#05').html($('#' + simaid + '-05').val());
            $('#06').html($('#' + simaid + '-06').val());
            $('#07').html($('#' + simaid + '-07').val());
            $('#08').html($('#' + simaid + '-08').val());
            $('#09').html($('#' + simaid + '-09').val());
            $('#10').html($('#' + simaid + '-10').val());
            $('#11').html($('#' + simaid + '-11').val());
            $('#12').html($('#' + simaid + '-12').val());
            $('#13').html($('#' + simaid + '-13').val());
            $('#14').html($('#' + simaid + '-14').val());
            $('#15').html($('#' + simaid + '-15').val());
            $('#16').html($('#' + simaid + '-16').val());
            $('#iid').html(simaid);

            //リストに書き戻すためのIDを取得する
            $().SPServices({
                operation: "GetListItems",
                async: false,
                listName: 'listZasekiSample',
                completefunc: function(xData, Status) {
                    $(xData.responseXML).SPFilterNode("z:row").each(function() {
                        if ($(this).attr("ows_Title") == simaid) {
                            iid = $(this).attr("ows_ID");
                        }
                    });
                }
            });

            //リストに書き戻す
            $().SPServices({
                operation: "UpdateListItems",
                async: false,
                batchCmd: "Update",
                listName: "listZasekiSample",
                valuepairs: [
                    ["za", $("#01").text()],
                    ["zb", $("#02").text()],
                    ["zc", $("#03").text()],
                    ["zd", $("#04").text()],
                    ["ze", $("#05").text()],
                    ["zf", $("#06").text()],
                    ["zg", $("#07").text()],
                    ["zh", $("#08").text()],
                    ["zi", $("#09").text()],
                    ["zj", $("#10").text()],
                    ["zk", $("#11").text()],
                    ["zl", $("#12").text()],
                    ["zm", $("#13").text()],
                    ["zn", $("#14").text()],
                    ["zo", $("#15").text()],
                    ["zp", $("#16").text()]
                ],
                ID: iid,
                completefunc: function(xData, Status) {
                    // alert("data saved");
                }
            });
        });

        //全部の島の座席数合計(全部と部署ごと)をカウント
        function countZaseki() {
            var numB01 = 0;
            var numB02 = 0;
            var numB03 = 0;
            var numB04 = 0;
            var numB05 = 0;
            var numB06 = 0;
            var numB07 = 0;

            $('.zaseki').each(function() {
                if ($(this).val() == '部署01') {
                    numB01++;
                } else if ($(this).val() == '部署02') {
                    numB02++;
                } else if ($(this).val() == '部署03') {
                    numB03++;
                } else if ($(this).val() == '部署04') {
                    numB04++;
                } else if ($(this).val() == '部署05') {
                    numB05++;
                } else if ($(this).val() == '部署06') {
                    numB06++;
                } else if ($(this).val() == '部署07') {
                    numB07++;
                }

            });

            //集計
            $('#numAll').html($('.zaseki').length);
            $('#numB01').html(numB01);
            $('#numB02').html(numB02);
            $('#numB03').html(numB03);
            $('#numB04').html(numB04);
            $('#numB05').html(numB05);
            $('#numB06').html(numB06);
            $('#numB07').html(numB07);
        }

        //部署別colorのclassを削除
        function remColorClass(obj) {
            simaid = $(obj).attr('id').slice(0, 3);
            var classVal;
            var classVals;
            for (var j = 1; j < 17; j++) {
                classVal = $('#' + simaid + '-' + ('00' + j).slice(-2)).attr('class') + '';
                classVals = classVal.split(' ');
                for (var i = 0; i < classVals.length; i++) {
                    if (classVals[i].indexOf('color') !== -1) {
                        $('#' + simaid + '-' + ('00' + j).slice(-2)).removeClass(classVals[i]);
                    }
                }
            }
        }

        //島の部署別colorのclassを付加
        function addColorClass(obj) {
            simaid = $(obj).attr('id').slice(0, 3);
            for (var i = 1; i < 17; i++) {
                $('#' + simaid + '-' + ('00' + i).slice(-2)).addClass('color' + $('#' + simaid + '-' + ('00' + i).slice(-2)).val());
            }
        }

    });
</script>

部署名じゃなくて個人名で表示したいとき

ここのページに、ユーザアカウントの名前とか部署名とかを取得する方法が載っています。
部署名を選択肢から取得するところをこれに置き換えたら、個人名も入れることができます。

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

【静的サイト】AWS独自ドメインでhttpsにするやり方

目的

独自ドメインにてhttpsにする。

使う機能

ASWの以下サービスを使います。
S3
AWS Certificate Manager(ACM)
CloudFront
Route 53

前提

S3にてアップ済み。
独自ドメインを取得している。

やり方

①AWS Certificate Manager(ACM)にてSSL/TLSの証明書を取得する。

(1)AWSのサービス検索でcmと打ったら出てきます。
(2)ACMの中に入ったら、必ず、リージョンを米国東部(バージニア北部)に変更しましょう。
 かなり重要です。私もここでハマりました。。
(3)パブリック証明書のリクエストを選択して、「証明書のリクエスト」をクリック
(4)ドメイン名の空欄に独自ドメインを入れましょう。
 例)*.example.com
 米印をつけて入れると、ワイルドカードになります。
 「次へ」をクリック
(5)「DNSの検証」を選択して、「確認」をクリックし、「確定とリクエスト」をクリック。
(6)すると、証明書の画面になり、状況が保留になっていると思います。
  名前のところをクリックすると広がり、「route53でのレコードの作成」があると思いますので、クリックします。
  route53以外で、独自ドメインを取得された方は、別の方法でレコードを作成する必要があります。
(7)しばらく待つ(長いと1時間以上)と状況が「発行済み」に変わります。

②CloudFrontの設定をする。

(1)AWSのCloudFrontへアクセスして、「create distribution」をクリックします。
(2)「Get Started」をクリックします。
(3)「Origin Domain Name」の空欄をクリックすると、S3のドメインが上がってくるので、選択します。
(4)Alternate Domain Names(CNAMEs)に独自ドメイン(サブ)を記載します。
 (例)www.example.com
(5)SSL Certificate
Custom SSL Certificate (example.com)を選択します。
 空欄をクリックすると先ほど登録した証明書が出てくると思いますので、選択します。
 この時、もしリージョンを東京で登録した場合は、出てきません。。
他は全てデフォルトのままで問題ないです。「create distribution」をクリックします。
(6)暫く待ち、Statusが『In Progress』から『Deployed』になれば完了です。

③route53の設定をする。

サブドメインのレコードセットでtypeAでAlias「yes」ですると、
『Alias Target』には作成したCloudFrontディストリビューションが選択できるようになっているので、
選択します。
これで、完了です。

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

switch文の比較、JavaScriptは'==='、PHPは’==’

同じswitch文を使って出力結果の違いを比較しよう

下はJSのコードですが、PHPで考える場合は読み替えてください。すなわち、num$numconsole.log(~)echo ~と読み替えてください。

JavaScriptとPHP
// A
switch(num) {
  case 5:
    console.log('整数の5');  
    break;
  default:
    console.log('該当なし');
    break;
}

// B
switch(num) {
  case '5':
    console.log('文字列の5');
    break;
  default:
    console.log('該当なし');
    break;
}

結果

155081659966.jpg

なぜこうなるのか

式を比較するときに、JavaScriptは厳密等価演算子(===)を使った厳密な比較を行い、PHPは等価演算子(==)を使った緩やかな比較を行うから。

JavaScriptのソース

switch文はまず始めに式を評価します。次に (厳密等価演算子===を使用して) 式が入力式の結果と評価される値が等しい最初の case 節を探し、…
 
switch - JavaScript | MDN

PHPのソース

switch/case が行うのは、 緩やかな比較 であることに注意しましょう。
PHP: switch - Manual

PHPでも厳密に比較したい

PHP
// A
switch(true) {
  case $num === 5:
    echo '整数の5';  
    break;
  default:
    echo '該当なし';
    break;
}

// B
switch(true) {
  case $num === '5':
    echo '文字列の5';
    break;
  default:
    echo '該当なし';
    break;
}

このように書くと厳密な比較になります。結果は以下の通り。なお、「JavaScript」と「PHP」の結果は、同じswitch文を使って出力結果の違いを比較しようのところで紹介しかコードを使ったときの結果で、「PHP(厳密)」はここで紹介したコードを使ったときの結果です。
155081659966.jpg

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

Vueで画像を遅延読み込みするライブラリ v-lazy-image

先日書いた表示速度改善の続きで、画像の遅延読み込みをするために、ライブラリを探してみたところ、v-lazy-imageが良い感じだったので紹介。

導入

$ npm install v-lazy-image --save

使い方

App.vueとかでプラグインとして読み込む場合

import Vue from "vue";
import { VLazyImagePlugin } from "v-lazy-image";

Vue.use(VLazyImagePlugin);

必要な箇所で個別に使う場合

import VLazyImage from "v-lazy-image";

export default {
  components: {
    VLazyImage
  }
};

あとは公式にある通り、v-lazy-imageタグを使ってやれば良い。

<template>
    <v-lazy-image src="http://lorempixel.com/400/200/" />
</template>

もちろん、propsやdataの値を渡すこともできる。

<template>
    <v-lazy-image :src="imageURL" />
</template>

<script>
import VLazyImage from "v-lazy-image";
export default {
    components: {
        VLazyImage
    },
    props: {
        imageURL: {
            type: String,
            default: null
        }
    }
}
</script>

あとは、出力されるimgタグにv-lazy-imagev-lazy-image-loadedのclassが付与されるので、こんな感じでアニメーションをつけることができる。

<style scoped>
.v-lazy-image {
  filter: blur(10px);
  transition: filter 0.7s;
}
.v-lazy-image-loaded {
  filter: blur(0);
}
</style>

最初はvue-lazyloadを使おうかと思ってたけど、画像の遅延読み込みのためだけならv-lazy-imageの方が軽くて良い感じ。

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

第2回フロントエンド調査発表資料

第2回フロントエンド調査発表
~TypeScript/Sass/webpack~

前回のおさらい

第1回フロントエンド調査発表はこちら

  1. JavaScriptの開発効率を向上したい
    • TypeScriptを使ってみよう
  2. CSSの保守性を向上したい
    • Sassを使ってみよう
    • BEMを取り入れてみよう
  3. ページ表示速度を改善しUXを向上したい
    • webpackを使ってみよう
    • SPAを取り入れてみよう

今回の話題

TypeScript、Sass、webpackを使ったサンプルで、どんな利点があるのか説明します

TypeScript/Sass/webpackの例

-前提知識-

  • TypeScriptやSassで書いたコードはブラウザで解釈できる言語に変換する必要がある
    • TypeScript➡JavaScript
    • Sass➡CSS
  • この変換のことをトランスパイルという

サンプルページ

75b5fe116d564c6994894c2341617214.gif

  • ボタンをクリックすると日付が表示されるページ

f87c4cbf718c94c7dfe3adf5d470c209.png

  • ボタンの装飾➡CSS
  • ボタンクリック時の動作➡JavaScript

0c72e730d493af65b009dcde920d7c1d.png

  • ボタンの装飾➡Sass
  • ボタンクリック時の動作➡TypeScript

Sass

まず、普通のCSSで書いた場合
f11fe7009d3bad5a3f0bc575137bc225.png

  • CSSと実際の構造が直観的に一致しない
  • 色などの共通な設定を管理しにくい

Sass(SCSS記法)で書くと構造がわかりやすい!
4f7862332cc17b5442576b9b4e8cf363.png

  • ネストしたブロックでCSSの構造が直観的で分かりやすい
  • 変数が使えるので色などを管理しやすい

TypeScript

4b550c3c560d9c192f212de0af682368.png

型を明示するのでどんな処理なのか把握しやすい

f135fe75f50c3739a76b1b906e16fd4e.png

  • コーディング中、トランスパイル時に構文エラーがわかる
    • JavaScriptはエラーに気付かず見逃すケースもある

webpack

e28756241eace1e9dfd6fa6ab723bb6f.png

  • JavaScriptやCSSをバンドルしjsを吐き出す
  • トランスパイル~バンドルの自動化もできる

さきほどのJavaScriptとCSSをwebpackでバンドル

787523bdbbdd4a64e169ee6acb5e0281.png

  • 不要な改行やスペースが削除されている

f2ec384668856412f9dec13258bb377d.png

  • 変数宣言・変数名が最適化されている

ちゃんと動く
07a93d84dc94128df0d593a1185526e3.png

まとめ:TypeScript/Sass/webpackを使えば・・・

  • 見やすいコード&静的チェックで開発効率向上
  • CSSの複雑化回避、保守性向上
  • webpackによる不要コード削除→バンドルで軽量化
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

JavaScript の Number の最大値

事象

// 20 桁の整数
console.log(12345678901234567890); // 12345678901234567000 (18 - 20 桁目が 000 になってしまった)

Number.MAX_VALUE

// JavaScript において表すことが可能な最大数
console.log(Number.MAX_SAFE_INTEGER); // 9007199254740991
// Integer かどうか
console.log(Number.isInteger(12345678901234567890)); // true
// safe integer かどうか
console.log(Number.isSafeInteger(12345678901234567890)); // false
var x = 12345678901234567890;
var y = 12345678901234567891;
console.log(x === y); // true

おまけ

JSON Viewer (JSON Formatter) を利用していて気づきました
json_formatter.png

参考

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

【翻訳】JavaScript開発者が知るべき33のコンセプト リンク集

この記事について

この記事は 33 concepts every JavaScript developer should know. というリポジトリの翻訳です。

GitHub上で日本語版リポジトリを作成して、翻訳リストにマージして貰ったのですがそのままだと誰も見にこなそうなので、Qiita にも共有しておきます。

日本語版と言ってもリンクタイトル部分が翻訳出来ていないので、協力してくれる方は是非プルリクを投げてください。

記事も動画も全て英語なので少ししんどいですが、2018年のTOPオープンソースプロジェクトの1つに選ばれたりしているので有益なはずです :imp:

日本語版リポジトリ

JavaScript開発者が知るべき33のコンセプト

目次 (table-of-contents)

  1. コールスタック (Call Stack)
  2. プリミティブ型 (Primitive Types)
  3. 値型と参照型 (Value Types and Reference Types)
  4. Implicit, Explicit, Nominal, Structuring and Duck Typing
  5. == vs === vs typeof
  6. 関数スコープ、ブロックスコープ、静的スコープ (Function Scope, Block Scope and Lexical Scope)
  7. 式 (Expression) vs 文字 (Statement)
  8. 即時関数、モジュール、名前空間 (IIFE, Modules and Namespaces)
  9. メッセージキューとイベントループ (Message Queue and Event Loop)
  10. setTimeout, setInterval and requestAnimationFrame
  11. JavaScriptエンジン (JavaScript Engines)
  12. ビット演算子、型付き配列、バッファ (Bitwise Operators, Type Arrays and Array Buffers)
  13. DOMとレイアウトツリー (DOM and Layout Trees)
  14. ファクトリとクラス (Factories and Classes)
  15. this, call, apply and bind
  16. new, Constructor, instanceof and Instances
  17. プロトタイプ継承とプロトタイプチェーン (Prototype Inheritance and Prototype Chain)
  18. Object.createとObject.assign (Object.create and Object.assign)
  19. map, reduce, filter
  20. 純粋関数、副作用、状態の変化 (Pure Functions, Side Effects and State Mutation)
  21. クロージャ (Closures)
  22. 高階関数 (High Order Functions)
  23. 再帰 (Recursion)
  24. コレクションとジェネレータ (Collections and Generators)
  25. プロミス (Promises)
  26. async/await
  27. データ構造 (Data Structures)
  28. 高負荷処理とBigO記法 (Expensive Operation and Big O Notation)
  29. アルゴリズム (Algorithms)
  30. 継承、ポリモーフィズム、コードの再利用 (Inheritance, Polymorphism and Code Reuse)
  31. デザインパターン (Design Patterns)
  32. 部分適用、カリー化、ComposeとPipe (Partial Applications, Currying, Compose and Pipe)
  33. 綺麗なコード (Clean Code)

1. コールスタック (Call Stack)

記事

動画

⬆ トップへ戻る


2. プリミティブ型 (Primitive Types)

記事

ビデオ

⬆ トップへ戻る


3. 値型と参照型 (Value Types and Reference Types)

記事

ビデオ

⬆ トップへ戻る


4. Implicit, Explicit, Nominal, Structuring and Duck Typing

記事

### ビデオ

⬆ トップへ戻る


5. == vs === vs typeof

記事

ビデオ

⬆ トップへ戻る


6. 関数スコープ、ブロックスコープ、静的スコープ (Function Scope, Block Scope and Lexical Scope)

記事

ビデオ

⬆ トップへ戻る


7. 式 (Expression) vs 文字 (Statement)

記事

ビデオ

⬆ トップへ戻る


8. 即時関数、モジュール、名前空間 (IIFE, Modules and Namespaces)

記事

ビデオ

⬆ トップへ戻る


9. メッセージキューとイベントループ (Message Queue and Event Loop)

記事

ビデオ

⬆ トップへ戻る


10. setTimeout, setInterval and requestAnimationFrame

記事

ビデオ

⬆ トップへ戻る


11. JavaScriptエンジン (JavaScript Engines)

記事

ビデオ

⬆ トップへ戻る


12. ビット演算子、型付き配列、バッファ (Bitwise Operators, Type Arrays and Array Buffers)

記事

### ビデオ

⬆ トップへ戻る


13. DOMとレイアウトツリー (DOM and Layout Trees)

記事

### ビデオ

⬆ トップへ戻る


14. ファクトリとクラス (Factories and Classes)

記事

### ビデオ

⬆ トップへ戻る


15. this, call, apply and bind

記事

### ビデオ

⬆ トップへ戻る


16. new, Constructor, instanceof and Instances

記事

⬆ トップへ戻る


17. プロトタイプ継承とプロトタイプチェーン (Prototype Inheritance and Prototype Chain)

記事

### ビデオ

⬆ トップへ戻る


18. Object.createとObject.assign (Object.create and Object.assign)

記事

### ビデオ

⬆ トップへ戻る


19. map, reduce, filter

記事

### ビデオ

⬆ トップへ戻る


20. 純粋関数、副作用、状態の変化 (Pure Functions, Side Effects and State Mutation)

記事

### ビデオ

⬆ トップへ戻る


21. クロージャ (Closures)

記事

### ビデオ

⬆ トップへ戻る


22. 高階関数 (High Order Functions)

記事

### ビデオ

⬆ トップへ戻る


23. 再帰 (Recursion)

記事

### ビデオ

⬆ トップへ戻る


24. コレクションとジェネレータ (Collections and Generators)

記事

### ビデオ

⬆ トップへ戻る


25. プロミス (Promises)

記事

### ビデオ

⬆ トップへ戻る


26. async/await

記事

### ビデオ

⬆ トップへ戻る


27. データ構造 (Data Structures)

記事

### ビデオ

⬆ トップへ戻る


28. 高負荷処理とBigO記法 (Expensive Operation and Big O Notation)

記事

ビデオ

⬆ トップへ戻る


29. アルゴリズム (Algorithms)

記事

⬆ トップへ戻る


30. 継承、ポリモーフィズム、コードの再利用 (Inheritance, Polymorphism and Code Reuse)

記事

### ビデオ

⬆ トップへ戻る


31. デザインパターン (Design Patterns)

記事

### ビデオ

⬆ トップへ戻る


32. 部分適用、カリー化、ComposeとPipe (Partial Applications, Currying, Compose and Pipe)

記事

### ビデオ

⬆ トップへ戻る


33. 綺麗なコード (Clean Code)

記事

ビデオ

⬆ トップへ戻る

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

laravel-mix + Vue.js (ES) + WebWorker (TS)

追記

2019-02-28 12:33

よさそう。
GoogleChromeLabs/comlink: Comlink makes WebWorkers enjoyable.
参考: WebWorkerをenjoyableにするComlinkとは何者か - Qiita


概要

laravel-mix + Vue.js (ES2018+) + ロジック部分は TypeScript というプロジェクトに、ちょっと Web Worker を導入したくなったのでやったというものです。
この記事は「こうやったら出来た」というメモでありベストプラクティスではないので、 Web Worker 初歩の参考の1つ程度にしていただければと思います。

Worker とは

Worker です。非同期処理による似非マルチスレッドではなく、真のマルチスレッドをもたらします。恐らく。
詳細や正確なところはは色んな方が解説されているかと思うのでぐぐってください!

Web Workers API - Web API | MDN

本記事では専用 Worker についてのみ言及します。

Worker の使い方

メインの JS とは別に Worker 用のコードを用意します。
インラインで文字列として記述したり別の <script> タグ中に記述したりでも大丈夫なそうですが、ここでは別ファイルとして用意します。

大まかに以下のような感じで使います。

main.js
import Worker from './path/to/file.worker.js'

const worker = new Worker()
// `new Worker('./path/to/file.worker.js')` とかでも出来るそうな…。
// 個人的にはコード中で参照されるファイルパスは
// `import ~ from ~` のように一箇所にまとめたい気持ちがあります。

worker.addEventListener('message', e => {
  const { data } = e

  console.log( data ) // => 500

  // worker を終了させる場合は実行。
  worker.terminate()
  // もしくは worker 側から `self.close()` を実行するとその場で worker が終了します。
})

// worker に `100` を送信。
worker.postMessage(100)
path/to/file.worker.js
addEventListener('message', e => {
  // `data` にはメインから渡された `100` が入ってくる。
  const { data } = e
  // `5` を掛けてメインスレッドに送信。
  postMessage( data * 5 )
})

今回やったこと

laravel-mix をコンパイラとして使っているプロダクトで、 Vue.js 製アプリケーション内から TypeScript 製 WebWorker を利用するということを行いました。

laravel-mix の設定

.webpackConfig() で Webpack の設定を行うだけです。

ローダーは worker-loader を以下のように設定しました。
Worker のファイル自体は TypeScript で書いていくので、 ts-loader も一緒に指定しています。

{
  module: {
    rules: [
      {
        test: /\.worker\.ts$/,
        use: [
          {
            loader: 'worker-loader',
            options: {
              name: '[name].js'
            }
          },
          'ts-loader'
        ]
      },
      {
        test: /\.ts$/,
        // Worker は Worker としてファイルを分離したいので除外設定 (そうしないとバンドルされちゃうかなぁと思って…)
        exclude: /\.worker\.ts$/,
        loader: 'ts-loader'
      }
    ]
  }
}

上記の設定に落ち着くまで以下のような挙動をされて躓きました。

  • worker-loadername を指定しないと出力ファイル名がハッシュ値になり、ビルドの度に違う Worker ファイルが生まれる。
  • worker-loaderpublicPath を指定するとそのディレクトリに出力されるが、 Vue.js アプリケーション内からの Worker 参照パスがおかしい。(存在しないパスを参照して 404 になる)

これらの理由から name を固定し、 publicPath を設定していません。
ただこれだと Worker ファイルの出力先が laravel-mix デフォルトの ./public 直下になってしまうので、ちょっと嫌だなぁとなっているところです。ちょっとどうにかしたい…。

tsconfig.json の設定

compilerOptions.lib"webworker" を追加します。
VSCode でも IntelliSense が効いてくれるようになります。

Worker を書く

TSで書きます。

path/to/file.worker.ts
interface IMessageEvent extends MessageEvent {
  data: number
}

addEventListener('message', (e: IMessageEvent) => {
  postMessage( e.data * 5 )
})

最低限これだけです。
最終的に Webpack で1つのファイルにまとめるので、 Worker 内でも importrequire() が使えます。

Vue.js コンポーネント内から Worker を利用する

利用します。

path/to/vue/component.vue
import Worker from 'path/to/file.worker.ts'

export default {
  // ...
  data(){
    return {
      num: 1
    }
  },
  methods: {
    handleWorker(){
      const worker = new Worker()

      worker.onmessage = e => {
        this.$data.num = e.data
        worker.terminate()
      }

      worker.postMessage( this.$data.num )
    }
  }
}

handleWorker() を実行する度に Worker を経由して $data.num の数値が5倍されていきます。


MDNの こことか にも結構複雑なコードがあったりするので、 Worker をラップした何かを使ってコントロールするのがいいんでしょうか。
素のまま Worker を使っていくのはなんだか苦しく感じました。

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

サロゲートペア、異体字、絵文字に対応した文字数の数え方

spread operatorだけでサロゲートペア文字列は対応できる

"?野屋".length //=> 4
[..."?野屋"].length // => 3

異体字や絵文字対応するなら、ライブラリを使う

import split from "graphemesplit";

"?野屋??葛飾区?葛?城市??".length // => 22
[..."?野屋??葛飾区?葛?城市??"].length // => 15
split("?野屋??葛飾区?葛?城市??").length // => 12

使うライブラリ

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

ノムリッシュ翻訳してくれるSlack bot(AWS lambda + APIGateway)

はじめに

ノムリッシュ翻訳とは日本語の文章を野村ファイナルファンタジー風用語(意識高い系)に変換してくれるWebサービスです。
ノムリッシュ翻訳 -ファビュラ・ノヴァ・ノムリッシュ

例えば、

私の好きな食べ物はお寿司です。

をノムリッシュ翻訳すると、

私の好きな食べ物は指揮官専用機として開発したウォ・スシです。
そしてその手には それぞれクリスタルが握られていた・・・

のように面白おかしく変換してくれます。

また、こちらの機能がnpmモジュールとして公開されているので、こちらを使ってSlackでノムリッシュ翻訳してくれるSlack botを作ろうと思い、実際に作ってみました。
npm nomlish
ノムリッシュ翻訳ライブラリをnpmに公開しました

完成イメージ

"nomlish 文章"と投稿すると、文章を翻訳してくれます。
Slack_bot_img.png

構成

lambda + APIGatewayを使用して、APIを作成し、Slackから作成したAPIをコールしレスポンスを受け取ります。
Slack_bot_architecture.png

準備

  • Slack アカウント
  • AWSアカウント
  • Node.js(npmコマンド) が動作する環境

構築手順

コード

lambdaで実行させるコードを準備します。
1. npm initコマンドで、Node.jsプロジェクトを作成
2. 先ほど紹介したノムリッシュモジュールをnpm i nomlishコマンドでインストール
3. プロジェクト直下にindex.jsを作成(下記参照)
4. index.jsとnode_modulesフォルダをまとめてZip化

index.js
var nomlish = require("nomlish");
exports.handler = (event, context, callback) => {
  console.log(event.text);
  var planeText = event.text.replace("nomlish ", "");
  var beforeText = planeText.replace(/\r?\n/g, '');
  var res = {};
  res.username = "ノムリッシュ";
  nomlish.translate(beforeText, 3).then(function(nomlishText) {
    res.text = JSON.stringify(nomlishText);
    callback(null, res);
  })
};

こちらはリクエストから渡ってくる文章を成形し、nomlish.translate()で翻訳し、結果をJSONに直してレスポンスを返す処理になります。

lambda

準備したコードを動作させる環境を作成します。AWS lambdaは関数単位で実行できるサーバレスのフルマネージドサービスです。
1. AWSコンソールにアクセスしてLambdaサービスを開く
2. 一から関数を作成(デフォルトのまま特に細かい設定は必要ありません)
3. 作成完了後、関数コード内、コードエントリタイプ「.zipファイルをアップロード」を選択し、先ほど作成したzipファイルをアップロード
image.png

これでlambdaの準備が完了です。

APIGateway

先ほど作成したlambdaとAPIGatewayを使って、SlackからコールされるAPIを作成します。Amazon API GatewayはAPIの作成、管理ができるフルマネージドなサービスです。
1. AWSコンソールにアクセスしてAPI Gatewayサービスを開く
2. APIの作成(デフォルトのまま特に細かい設定は必要ありません)
image.png
3. 「アクション」>「メソッドの作成」を選択し、プルダウンから「POST」を選択する
image.png
4. -POST-セットアップの画面で、先ほど作成したLambda関数名を入力する
image.png
5. 「統合リクエスト」を選択し、マッピングテンプレートを開き、「リクエストの Content-Type ヘッダーに一致するテンプレートがない場合」を選択する。さらに、Content-Typeに「application/x-www-form-urlencoded」を入力し、下記コードを追加する
image.png

## convert HTML POST data or HTTP GET query string to JSON

## get the raw post data from the AWS built-in variable and give it a nicer name
#if ($context.httpMethod == "POST")
 #set($rawAPIData = $input.path('$'))
#elseif ($context.httpMethod == "GET")
 #set($rawAPIData = $input.params().querystring)
 #set($rawAPIData = $rawAPIData.toString())
 #set($rawAPIDataLength = $rawAPIData.length() - 1)
 #set($rawAPIData = $rawAPIData.substring(1, $rawAPIDataLength))
 #set($rawAPIData = $rawAPIData.replace(", ", "&"))
#else
 #set($rawAPIData = "")
#end

## first we get the number of "&" in the string, this tells us if there is more than one key value pair
#set($countAmpersands = $rawAPIData.length() - $rawAPIData.replace("&", "").length())

## if there are no "&" at all then we have only one key value pair.
## we append an ampersand to the string so that we can tokenise it the same way as multiple kv pairs.
## the "empty" kv pair to the right of the ampersand will be ignored anyway.
#if ($countAmpersands == 0)
 #set($rawPostData = $rawAPIData + "&")
#end

## now we tokenise using the ampersand(s)
#set($tokenisedAmpersand = $rawAPIData.split("&"))

## we set up a variable to hold the valid key value pairs
#set($tokenisedEquals = [])

## now we set up a loop to find the valid key value pairs, which must contain only one "="
#foreach( $kvPair in $tokenisedAmpersand )
 #set($countEquals = $kvPair.length() - $kvPair.replace("=", "").length())
 #if ($countEquals == 1)
  #set($kvTokenised = $kvPair.split("="))
  #if ($kvTokenised[0].length() > 0)
   ## we found a valid key value pair. add it to the list.
   #set($devNull = $tokenisedEquals.add($kvPair))
  #end
 #end
#end

## next we set up our loop inside the output structure "{" and "}"
{
#foreach( $kvPair in $tokenisedEquals )
  ## finally we output the JSON for this pair and append a comma if this isn't the last pair
  #set($kvTokenised = $kvPair.split("="))
 "$util.urlDecode($kvTokenised[0])" : #if($kvTokenised[1].length() > 0)"$util.urlDecode($kvTokenised[1])"#{else}""#end#if( $foreach.hasNext ),#end
#end
}

設定が完了したら、APIをデプロイします。
6. 「アクション」>「APIのデプロイ」を選択し、「デプロイされるステージ」に[新たなステージ]を選択する
7. 「ステージ名」に適当な名前を入力し、「デプロイ」ボタンを押下する
image.png
8. デプロイが完了し、ステージエディター内にURLが表示される
image.png

以上でAPIGatewayの設定は完了です。

Slack

作成したAPIをSlackからコールする設定を行います。Outgoing Webhooksを使用するのですが、こちらは設定した言葉がトリガーとなって、SlackからPOSTのメソッドを送信し、指定した形式でJSONが返されると投稿してくれるものになります。
1. サイドバーの「Apps」を押下、App Directory画面内の検索窓に「Outgoing WebHooks」と入力しOutgoing WebHooksの設定画面を開く
image.png
2. 「Add Configuration」を押して、今回作成する設定を追加する
3. 各種設定する(今回使用するもののみ説明)
image.png
image.png
Chanel:適用するチャンネルの選択
Trigger Words(s):トリガーとなる言葉の設定、今回はnomulishを指定
URL(s):API URLの設定、先ほどAPIGatewayで作成したURLを指定
Customize Name:botが投稿する際の名前、ただし今回はAPIのレスポンスで名前を指定
Customeize Icon:アイコンの指定
4. 以上設定出来たら、「Save Settings」を押下、完成です!

雑談

実は当初、API部をGASで作成する予定でした。が、ノムリッシュのモジュールをバンドルするのに苦労して、今回の構成で作成することを決めました。こちらを応用すれば、天気を教えてくれるbotなども作れちゃいます!

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

Googleスプレッドシート – メルマガ風一括送信

今回はタイトル通り、
スプレッドシートにメールアドレスの一覧リストがあれば、それを順番に送信するプログラムを作成しました。
正直、担当者が抜けてるとかアドレスが抜けてるとか、そういったチェック処理はしてないです。(笑)

以下様々なGASの記事を紹介してます!
https://bzbot.work/

紹介記事
今回紹介している記事は以下です!
https://bzbot.work/2019/02/03/spreadsheet-email-2/

アドレス一覧シート

ここでは送信する宛先と担当者の名前を一覧で登録しておくシートで、数式など利用はしておらずそのままのデータを登録するイメージです。
image.png

内容テンプレシート

ここでは送信するための内容(本文)にあたる部分を書いていきます。
送信する人によって本文を毎回変えて送っていることはあまりないと思うので、内容(本文)のテンプレートを作っていきます。
※「宛先」と「担当者名」はプログラムで自動取得するため、空欄にしておいてください
image.png

メールテンプレ

ここでは最終的に送信する宛先と件名(統一)、本文を入れてます。
Toには以下数式を入れておきます。

=’内容テンプレ’!B1

次にSubjectですが、ここもメールによって内容変えることはあまりないと思うので今回は「メルマガ風一括送信」とつけます。
※コピペだとシングルクォートが全角になってしまう場合があります

最後にBodyですが、以下を入れておきます。

=’内容テンプレ’!B2&” さま”&char(10)&’内容テンプレ’!B3

すると、内容テンプレで取得した値を担当者であれば「さま」をつけた形にするなどカスタムできます。
image.png

GAS
function goGoMM() {
//アクティブシートで指定した(こっちの方が一般的ね(笑))
  var sheet = SpreadsheetApp.getActiveSpreadsheet();

  //「メーリングリスト」のシートをアクティブにして、シート情報をmListに取得
  var mList = sheet.setActiveSheet(sheet.getSheetByName("メールリスト"));
  //「内容テンプレ」のシートをアクティブにして、シート情報をbTempに取得
  var bTemp = sheet.setActiveSheet(sheet.getSheetByName("内容テンプレ"));
  //「メールテンプレ」のシートをアクティブにして、シート情報をmTempに取得
  var mTemp = sheet.setActiveSheet(sheet.getSheetByName("メールテンプレ"));

  //取得したmListの最終行を取得する
  var lastR = mList.getLastRow();
  Logger.log("【lastR】:" + lastR);

  //lastRは最初から最後の行までをカウントしているので、対象となるデータが入っている個数をカウントしてしまってます。(タイトルもカウントしているってこと)
  var popUp = Browser.msgBox("送信確認!","送信対象数"+lastR+"件です。(1行目もカウントしてます)実行しますか?", Browser.Buttons.OK_CANCEL);
  if (popUp == 'ok') {

    //取得した最終行までの情報を配列で取得する
    var mlvalue = mList.getRange(1, 1, lastR, 2).getValues();
    Logger.log("【mlvalue】:" + mlvalue);

    //lastRは6だが、1行目はタイトルなのでX回繰り返して欲しいため、iがより大きい場合は実行終了とする
    for(var i = 1; i < lastR; i++) {
      Logger.log("【mlvalue[" + i + "][0]】:" + mlvalue[i][0]);
      //mlvalueで取得した値を「内容テンプレ」の宛先にセット
      bTemp.getRange(1, 2).setValue(mlvalue[i][0]);
      Logger.log("【mlvalue[" + i + "][0]】:" + mlvalue[i][1]);
      //mlvalueで取得した値を「内容テンプレ」の担当者名にセット
      bTemp.getRange(2, 2).setValue(mlvalue[i][1]);
      //宛先と担当者名をセットし終わったら送信情報を取得
      var add = mTemp.getRange(1,2).getValue();
      var mailSubject = mTemp.getRange(2,2).getValue();
      var mailBody =mTemp.getRange(3,2).getValue();
      //送信情報をセットして送信!
      GmailApp.sendEmail(add, mailSubject, mailBody);
    }
    Browser.msgBox("送信しました");
  }
  else {
    Browser.msgBox("キャンセルしました");
  }
}

上記実行すると、以下ログが出力されます。

[19-02-03 07:22:59:721 JST] 【lastR】:6
[19-02-03 07:23:15:837 JST] 【mlvalue】:メール,担当者名,bzbot@bzbot.work,担当A,bzbot@bzbot.work,担当B,bzbot@bzbot.work,担当C,bzbot@bzbot.work,担当D,bzbot@bzbot.work,担当E
[19-02-03 07:23:15:838 JST] 【mlvalue[1][0]】:bzbot@bzbot.work
[19-02-03 07:23:15:840 JST] 【mlvalue[1][0]】:担当A
[19-02-03 07:23:16:253 JST] 【mlvalue[2][0]】:bzbot@bzbot.work
[19-02-03 07:23:16:255 JST] 【mlvalue[2][0]】:担当B
[19-02-03 07:23:16:804 JST] 【mlvalue[3][0]】:bzbot@bzbot.work
[19-02-03 07:23:16:806 JST] 【mlvalue[3][0]】:担当C
[19-02-03 07:23:17:204 JST] 【mlvalue[4][0]】:bzbot@bzbot.work
[19-02-03 07:23:17:206 JST] 【mlvalue[4][0]】:担当D
[19-02-03 07:23:17:665 JST] 【mlvalue[5][0]】:bzbot@bzbot.work
[19-02-03 07:23:17:666 JST] 【mlvalue[5][0]】:担当E

上記実行すると、「メールリスト」に入っているメーリングリストに対して担当者名とアドレスが取得され、送信したらまた次の値(担当者名とアドレス)をセットして送信を繰り返します。
繰り返す回数としては「メールリスト」の最終行文処理を繰り返すとしています。
※表示用の変数を用意すればしっかりと「lastR – 1」で正確な値5が出てくる記述は容易です(笑)

これでメールマガジン的な配信も簡単にできますね。
コードの可読性だったりは今勉強中なので精進します_φ( ̄ー ̄ )

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

angular.jsよりもAngularを推奨してもらったので、さっそく勉強してみた。

Angular.jsよりもAngularを推奨してもらったので、さっそく勉強してみた。

今日の勉強時間

一通り実行してみた結果、実際にかかった時間は30分ぐらいかも。
Angular.jsよりサンプルプログラムをインストールして実行するまでの時間は短く感じました!

前提

・npmがインストールされていること
・Node.jsのバージョン8.xまたは10.xがインストールされていること

僕は昨日の記事の中でインストール済みなので飛ばします。

参考:ANGULAR.JS公式チュートリアルのPhoneCat Tutorial Appはじめました。
https://qiita.com/ryuutamaehara/items/4f095b264f5e688ef1c1#comment-54fb8b28131e1bbf3996

なぜAngular?昨日はAngular.jsだったじゃん。

昨日の記事を見ていただいた方にコメントをいただきました。

「angularJS はもう古くなってしまっている」

ナント(´・ω・`)

WEB開発って時代の流れが速いっていうけど本当なんですね。

いままで顧シス担当やらメインフレームの運用とか〇〇みたいな現場しか回ったことなかった私はこの事に感動を覚えました。いいね。web系。
これからちょこっとずつ頑張っていきたいと思います('ω')ノ

では、今日から実際にオススメをいただいた「Angular」を勉強してみたいと思います。

さっそく公式サイトをチェック!

まずは公式サイトから!
驚くなかれ!な、なんと日本語だァァァァァァァ!('ω')ワーイ

参考:https://angular.jp/

トップページに「モバイルとデスクトップ、ひとつのフレームワーク」なんてオシャンなキャッチフレーズを見てわかる通り、Angularでは今の主要なデバイスのシステムを1つのフレームワークで構築可能な事が強みのようです。

では、まずはじめに

Angular.jsと同じくNode.jsとnpmを使うみたいですね。
この二つはこの記事の頭にも書きましたが、すでにインストール済みなので飛ばします。

Angular CLIをインストールする

ここも記事通りに進めてみます。
Angularは主にCLI(コマンドラインインタフェース)で操作を進めるみたいですね。
CUI嫌いだからwindows使っているんだけどなぁ...。

文句言っちゃダメですよね。はい。

コマンドプロンプトから以下のコマンドを実行します。

npm install -g @angular/cli

ワークスペースと初期アプリケーションを作成の作成

ワークスペースと初期アプリケーションを作成します。
次のコマンドを実行する前に作成したいディレクトリに移動しておいてくださいね。

ng new my-app

ng newコマンドでアプリケーションのひな型を作成されるようです。
my-appが作成されるアプリケーション名になります。

作成されるひな型プロジェクトは以下の構成を含むようです。
・my-appという名前のルートフォルダをもつ新しいワークスペース
・my-appと呼ばれる最初のスケルトンアプリケーションプロジェクト(srcサブフォルダ内)
・エンドツーエンドのテストプロジェクト(e2eサブフォルダ内)
・関連する設定ファイル

このアプリの中にはすぐに実行できるアプリが入ってるみたいですね。

サーバを起動する

作成したひな型の中にはサーバも含まれるみたいですね!
さっそく起動してアプリの動作を確認してみます。

cd my-app
ng serve --open

serverではなくserveですよ。(笑)
成功するとhttp://localhost:4200/が自動的にブラウザで開かれます。

Angularのアイコンとともに「Welcome to my-app! 」といった表記が画面が表示されていたら成功です。

Angularコンポーネントを編集してみる

./src/app/app.component.tsのファイルがAngularの構成管理ファイルらしいです。
画面上のデータ表示からユーザからの入力に基づいたアクションなどもここに記載するっぽいです。

この中に「my-app」という記載があるので、「My First Angular App」という文字列に変更してみます。
この状態で先ほど起動したアプリ画面を更新すると、「Welcome to my-app! 」といった表記が、「Welcome to My First Angular App! 」に変わったことが確認できます。

次にcssの設定をしてみます。

/src/app/app.component.css
h1 {
  color: #369;
  font-family: Arial, Helvetica, sans-serif;
  font-size: 250%;
}

元のブラウザに戻ると、cssが適用されたことが確認できます。

ここまでで今日の分のチュートリアルは完了です。

明日のおはなし

次のステップとして公式サイトには次のように記載されています。

・Tour of Heroesチュートリアルでは、実践的な追加学習が提供されています。それは、人材派遣会社がスーパーヒーローの従業員のグループを管理するのに役立つアプリを構築する手順を順を追って説明します。

なんか聞き覚えがあるような無いような…
タイバニ?なんだ?記憶が…w

・アーキテクチャガイドでは、モジュール、コンポーネント、サービス、依存性の注入(DI)などの重要な概念について説明します。特定のAngularの概念と機能に関する詳細なガイドの基礎を提供します。

今日は以上です!!眠い!(:3 」∠)

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

#ngular.jsよりもAngularを推奨してもらったので、さっそく勉強してみた。

Angular.jsよりもAngularを推奨してもらったので、さっそく勉強してみた。

今日の勉強時間

一通り実行してみた結果、実際にかかった時間は30分ぐらいかも。
Angular.jsよりサンプルプログラムをインストールして実行するまでの時間は短く感じました!

前提

・npmがインストールされていること
・Node.jsのバージョン8.xまたは10.xがインストールされていること

僕は昨日の記事の中でインストール済みなので飛ばします。

参考:ANGULAR.JS公式チュートリアルのPhoneCat Tutorial Appはじめました。
https://qiita.com/ryuutamaehara/items/4f095b264f5e688ef1c1#comment-54fb8b28131e1bbf3996

なぜAngular?昨日はAngular.jsだったじゃん。

昨日の記事を見ていただいた方にコメントをいただきました。

「angularJS はもう古くなってしまっている」

ナント(´・ω・`)

WEB開発って時代の流れが速いっていうけど本当なんですね。

いままで顧シス担当やらメインフレームの運用とか〇〇みたいないな現場しか回ったことなかった私はこの事に感動を覚えました。いいね。web系。
これからちょこっとずつ頑張っていきたいと思います('ω')ノ

では、今日から実際にオススメをいただいた「Angular」を勉強してみたいと思います。

さっそく公式サイトをチェック!

まずは公式サイトから!
驚くなかれ!な、なんと日本語だァァァァァァァ!('ω')ワーイ

参考:https://angular.jp/

トップページに「モバイルとデスクトップ、ひとつのフレームワーク」なんてオシャンなキャッチフレーズを見てわかる通り、Angularでは今の主要なデバイスのシステムを1つのフレームワークで構築可能な事が強みのようです。

では、まずはじめに

Angular.jsと同じくNode.jsとnpmを使うみたいですね。
この二つはこの記事の頭にも書きましたが、すでにインストール済みなので飛ばします。

Angular CLIをインストールする

ここも記事通りに進めてみます。
Angularは主にCLI(コマンドラインインタフェース)で操作を進めるみたいですね。
CUI嫌いだからwindows使っているんだけどなぁ...。

文句言っちゃダメですよね。はい。

コマンドプロンプトから以下のコマンドを実行します。

npm install -g @angular/cli

ワークスペースと初期アプリケーションを作成の作成

ワークスペースと初期アプリケーションを作成します。
次のコマンドを実行する前に作成したいディレクトリに移動しておいてくださいね。

ng new my-app

ng newコマンドでアプリケーションのひな型を作成されるようです。
my-appが作成されるアプリケーション名になります。

作成されるひな型プロジェクトは以下の構成を含むようです。
・my-appという名前のルートフォルダをもつ新しいワークスペース
・my-appと呼ばれる最初のスケルトンアプリケーションプロジェクト(srcサブフォルダ内)
・エンドツーエンドのテストプロジェクト(e2eサブフォルダ内)
・関連する設定ファイル

このアプリの中にはすぐに実行できるアプリが入ってるみたいですね。

サーバを起動する

作成したひな型の中にはサーバも含まれるみたいですね!
さっそく起動してアプリの動作を確認してみます。

cd my-app
ng serve --open

serverではなくserveですよ。(笑)
成功するとhttp://localhost:4200/が自動的にブラウザで開かれます。

Angularのアイコンとともに「Welcome to my-app! 」といった表記が画面が表示されていたら成功です。

Agularコンポーネントを編集してみる

./src/app/app.component.tsのファイルがAgularの構成管理ファイルらしいです。
画面上のデータ表示からユーザからの入力に基づいたアクションなどもここに記載するっぽいです。

この中に「my-app」という記載があるので、「My First Angular App」という文字列に変更してみます。
この状態で先ほど起動したアプリ画面を更新すると、「Welcome to my-app! 」といった表記が、「Welcome to My First Angular App! 」に変わったことが確認できます。

次にcssの設定をしてみます。

/src/app/app.component.css
h1 {
  color: #369;
  font-family: Arial, Helvetica, sans-serif;
  font-size: 250%;
}

元のブラウザに戻ると、cssが適用されたことが確認できます。

ここまでで今日の分のチュートリアルは完了です。

明日のおはなし

次のステップとして公式サイトには次のように記載されています。

・Tour of Heroesチュートリアルでは、実践的な追加学習が提供されています。それは、人材派遣会社がスーパーヒーローの従業員のグループを管理するのに役立つアプリを構築する手順を順を追って説明します。

なんか聞き覚えがあるような無いような…
タイバニ?なんだ?記憶が…w

・アーキテクチャガイドでは、モジュール、コンポーネント、サービス、依存性の注入(DI)などの重要な概念について説明します。特定のAngularの概念と機能に関する詳細なガイドの基礎を提供します。

今日は以上です!!眠い!(:3 」∠)

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

ローカルからnode.jsを削除する

node.jsをインストーラからインストールしてしまった

node.js1日目です。

何も考えずnode.jsをインストーラ経由でインストールしてしまいました。
@gaikitan です。 (本業はiOSエンジニアをやっています。)

node.jsのローカルからの削除ですが、非常に簡単です。
node.jsの削除は5秒で終わったのですが、当記事の作成には1時間かけております。はい。

この度node.jsを使う事になりまして、「とりあえずnode.js入れといたらいいんやろ」 みたいな感じで適当にインストーラからインストールしてみました。
しかし様々な記事で、 「node.jsのバージョン管理は面倒だから、今すぐnodebrewに変えたほうがいいよ」 と言われました。

「そんなに言うなら、一旦ローカルのnode.js消してnodebrew経由にするか」

ローカルのnode.jsを削除する

検索して沢山出てきたこのコマンド

$ lsbom -f -l -s -pf /var/db/receipts/org.nodejs.pkg.bom \
| while read i; do
  sudo rm /usr/local/${i}
done
sudo rm -rf /usr/local/lib/node \
     /usr/local/lib/node_modules \
     /var/db/receipts/org.nodejs.*

(参考資料)How do I uninstall nodejs installed from pkg (Mac OS X)?
https://stackoverflow.com/questions/9044788/how-do-i-uninstall-nodejs-installed-from-pkg-mac-os-x

これで本当に消せた人いるんですか?
コピペしましたが

can't open /var/db/receipts/org.nodejs.pkg.bom: No such file or directory
**** Can't open /var/db/receipts/org.nodejs.pkg.bom.

と言われました。コマンドの意味を理解せずに実行するのは絶対に辞めましょう(自戒)

node.jsの削除

node.jsの実行時のフルパス取得

$ which node
→ /usr/local/bin/node

実際の削除

$ sudo rm -rf /usr/local/bin/node

削除できたかどうかの確認

$ node -v
bash: command not found: node

ついでにnpmも削除

$ sudo rm -rf ~/.npm

削除できたかどうかの確認

$ npm -v
bash: command not found: npm

消えてた。 終わり。

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