Code Serendipity

Keyword: Ruby, Python, javascript, RoR, heroku, AWS...

Code Serendipity

Keyword: Ruby, Python, wordpress, javascript, AWS...

全然Windows開発したことのない人がVisual StudioでVisual C++でHello Worldやる時に読むといいまとめ(超基本)

https://isocpp.org/files/img/cpp_logo.png

Visual Studio とはmicrosoft統合開発環境である。今回はMacに入れたwindowsVisual StudioからC++でコードを書くという初めての試みの3乗をやるので、念のためブログに調べたことを書いておく。ちなみに私は今までターミナルのvimRailsアプリを作るという素朴な開発環境,Command+Rを高速で行う技術だけ磨いていた, IDEは使ったことなかった。今まで使ってきた言語はRuby, python, PHP … 総じて、コンパイルのいらない、いわゆるインタプリタ言語というやつで、恥ずかしながら、アドレスとかポインタとかそこまで意識してこなかった。。。

統合開発環境とは、なにか。改めて。

IDE(統合開発環境とは)

プログラムの作成には、テキストエディタコンパイラという 2種類の道具を使う必要があった。

分割コンパイル等によってプログラムのファイル構成が複雑になると、ソースから実行ファイルを得るためのビルド手順を自動化するツール(make や Ant、MSBuild など) が必要になる。

また、プログラム作成にはこれら以外に、動作時のプログラムの間違いを見つけて修正する手助けをするデバッガ、テストを自動化するテストツール、プログラムの各部分の性能を細かく測定することで性能向上の手助けをするプロファイラ、プログラムの修正過程を管理するバージョン管理システム、必要な機能追加やプログラムの誤りの修正状況を管理するバグ管理システム、デバッグ/リリースビルドや動作ターゲットや派生開発のターゲットなどによる設定の違いを管理する構成管理ツール、関係する画面設計などを手助けするGUI作成ツール、体系的なプログラムの修正を補助するリファクタリングツール、など、さまざまなツールを使う必要がある。

これらのツールを一つのツールから統一的扱うことが出来るようにしたのが、統合開発環境 (Integrated Development Environment, IDE) である。

Visual Studio 統合開発環境の使い方

Visual Studio 用語

Visual Studio でのプログラム作成には、以下の流れがある。 1. VS.NETの起動 2. プロジェクト(Windowsアプリケーション)の新規作成 3. プロジェクトのビルド(=プログラムの生成) 4. 生成されたプログラムの実行 5. VS.NETの終了(=プロジェクトの保存)

VS.NETで作ったプログラム(「.NETプログラム」と呼ばれる)は、「.NET Framework」という実行プラットフォーム上で動作する。

http://image.itmedia.co.jp/ait/articles/0405/19/dt-easyvs01.gif

プロジェクトとはなにか

VS.NETでは、1つの「(VS.NETの)プロジェクト」から1つの「プログラム」が生成できる。なお「プロジェクト」とは、プログラムの生成に必要な複数のファイル(「ソース・ファイル」と呼ばれる)をまとめたものである。つまりプロジェクトとは、VS.NET専用のフォルダのようなもので、複数のソース・ファイルを整理するための入れ物である。プログラムを作成するには、まず、このVS.NETのプロジェクトを1つ新規作成する必要がある。これには、IDEのメニュー・バーから[ファイル]―[新規作成]―[プロジェクト]を選択する。

連載簡単!Visual Studio .NET入門:第1回 初めての「Visual Studio .NET」 (3/4) - @IT

Hello World してみよう

C++の教科書の簡単なサンプルコードをVisual C++で動かす方法はふたつあります。一つは「空のプロジェクト」を作る方法、もう一つはVisual Studioが用意するコンソール・プリケーションのテンプレートを利用する方法です。まず、「空のプロジェクト」を作る方法を示します。メニューから「ファイル/新しいプロジェクト」を選びます。左側のテンプレートで「Visual C++」を選び、「Win32 コンソール アプリケーション」を選びます。下のところでプロジェクトの「名前」や「場所」を適当に決めます。

アプリケーションの設定で「コンソール アプリケーション」を選び、追加のオプションを「空のプロジェクト」として「完了」ボタンを押します。 メニューから「プロジェクト/既存項目の追加」を選びます。「C++ ファイル(.cpp)」を選び、名前を付けます。ここでは「Hello.cpp」とします。コードを打ち込んだら、打ち込んだら、メニューから「デバッグデバッグなしで開始」を選びます。

J.S.エコハのブログ: 初心者がVisual C++で"Hello World"を表示させる方法

C++ とは

なお、以下の例には

C++の超基本 - PukiWiki

を大いに参考させていただいた。

最初におまじないを入れる(後述)。

#include<iostream>
using namespace std; 

main(){} の中に処理をかいていく

int main(){ 

 処理1;
 処理2;
 ........ 

 return 0;
}

キーボードからの入力出力

変数xにキーボードから値を入力させるには、

  • cin: console input の省略形
  • cout: console output の省略形

を使う。 改行は、

  • endl: end line の省略形

で可能。 これらの変数は、

#include <iostream>

で読み込んでいる、C++標準ライブラリのI/Oストリームで提供されている。

cin >> x;
//プログラムを実行すると入力待ちになる、値をキーボードで打ってリターンを押せば入力される。

//変数xの値を画面に出力するには

cout << x;

// 改行して出すには endl

cout << "整数 a=" << a << endl; cout << "実数 x=" << x << endl;

ループ

for

for(int i=0; i<10; i++) cout << i << endl;

while

int i=0;
while( i<10 ){
 cout << i << endl;
 i++;
}

if, else if

elsif ではなくて else if とスペースはいることに注意

if(A) X;
else if(B) Y;
...
else Z;

配列

//型 配列[配列の数];

 
double v[3]; // doubleは実数の型を示す。v[0]   v[1]   v[2]ができた

// 初期値を一気に入れるなら{を使う。 double v[3]={1, 2, 3};

ファイルに書き込む

#include <fstream> // これでfout関数などが使えるようになる
int main(){

 .....

 ofstream fout("file.txt"); // ファイル名を命名

 .....
 
 fout << "Hello, World!" << endl; // 書き込み

 .....
 
 fout.close(); //  ファイルを保存して閉じる

 .....

 return0;
}

アドレスとアクセス

変数の前に「&」を付けると、その変数のメモリアドレスを表現できる。

cout << &a << endl; //0012FF50

アドレスが0012FF55 とかのとき、*(0012FF55) とすれば、そのアドレスにあるデータにアクセスできる。アスタリスク+アドレスで、そのアドレスのデータにアクセスできると覚えておく。

アドレスとポインタ

アドレスを保存するためだけの、変数を、データ型に*をつけることで表現できる。

たとえば、ある整数 int a=2; があったとき、 そのaのアドレスを保存する変数を、 int* pointer; と宣言することができて、実際にはaのアドレスは&aで示されるから、 pointer = &a;

// データの型* 変数;


int* p; //整数のデータのアドレス用のポインタ
int a = 100;
p = &a;

配列とポインタ

double v[3]={1,2,3};

としたとき、v[0]のアドレスは、vなのである。 連続する配列のアドレスは連続しているので、&(v[1]) == (v + 1), &(v[2]) == (v + 2) である。

足し算関数sum()を作ってみる

#include <iostream>
using namespace std;

// ポイント:main関数より先に、さらに、main関数の外に宣言しているのに注目

int sum(int a, int b); //関数sumの宣言
void output(int a); //関数outputの宣言
 
int main(){
    int a;
    a=sum(2,5); //関数sumの呼び出し
    output(a); //関数outputの呼び出し
    return 0;
}

//関数sumの定義


int sum(int a, int b){
    int c=a+b;
    return c;
}

//関数outputの定義
void output(int a){
    cout << "答えは" << a << "です。" << endl;
}

 

関数とポインタ

以下、引数が増えていく関数を作ろうとしているが、間違っている例。

#include <iostream>
using namespace std;
void plusone(int x); 
int main(){ 
    int a=1;
    plusone(a);
    cout << a << endl;
    return 0;
} 
void plusone(int x){
    x++;
}

main関数の変数aとplusoneの変数xは全く別物であって、plusone()がmain()のaに代入されていないことによる。 そこで、ポインタを使ってaのアドレスにアクセスしてaの値を書き換える。

int main(){ 
    int a=1;
    plusone(&a); // &でaのアドレスを取得。
    cout << a << endl;
    return 0;
} 
void plusone(int* p){ // aのアドレスを入れて
    (*p)++; // そのアドレスのデータ(*p)を1増やす。
}

ファイルを分割してsumプログラムを作る

C++では一般的に、ヘッダー部(.h)と実装部(.cpp)を分ける。そのほうがコンパイル時間が早くなる・ビルド済みの実装部と要件定義を示すヘッダー部だけ配布するというシチュエーションがありうるかららしい

main.cpp

#include <iostream>
#include "func.h" // ヘッダファイルである、func.h (後述)を読み込む。iostreamはもともと用意されているので、<>で囲むが、自分で作ったヘッダファイルは二重かっこ"で囲む。
using namespace std; 

int main(){
    int a;
    a=sum(2,5); //関数sumの呼び出し
    output(a); //関数outputの呼び出し
    return 0;
}

func.cpp

#incl ude <iostream>
using namespace std;
func sum(int a, int b){
   c = a + b;
   return c;
}
void output(int a){
    cout << "答えは" << a << "です。" << endl;
}

func.h

関数の宣言だけを集めたファイル。ヘッダファイルという。 コンパイルのいらない部分だけを書くようにする。 したがっておまじない(include…)はいらない

int sum(int a, int b); 
void output(int a);

dll ファイルとは

Windowsを使ったことのなかった自分は、DLL??は??という感じであったが・・・ なんのことはない、Windowsにおける実行ファイルの拡張子である。 Windows.NET Frameworkの実装においては、アセンブリにはプロセスアセンブリ (EXE) とライブラリアセンブリ (DLL) の2種類がある。DLLは、EXEファイルから呼び出されて、EXEファイルに機能を提供するためのファイル。DLLは、Dynamic Linking Library(ダイナミック・リンキング・ライブラリ)の略で、よく使う機能は互いに共同で使えるように独立させておき、必要に応じ てアプリケーションが共同して使えるようにしたソフトである。EXEを補佐する役割があるのがDLLと考えればよいようだ。

Macしか使ったことのない人間がBootCampでWindowsを入れてMacライクにする

https://support.apple.com/library/content/dam/edam/applecare/images/ja_JP/macos/macos-sierra-boot-camp-hero.jpg

Windows OSでしか動かないソフトウェア, ハードウェアをどうしても使いたかった。macbook2016 8gbでは、Visual Boxみたいな仮想環境だと動作が鈍くなりそうだと思い、Mac 標準機能であるBootCampを利用することにした。 なおparacellという選択肢もあったが、ハードウェア周りに弱い(USBポートを認識しなかったりする?)らしいのでやめておいた。

Bootcamp でwindowsをいれるには

  • Windows のライセンスキーをAmazonかなんかで手に入れる。1.3万円程度であった。
  • Windows のイメージファイル(*.ios)を手に入れる。windows公式サイトから落とせる。
  • Boot Camp アシスタントを開き、該当するイメージファイルを選択して進めていく。

公式サイトを見て入れば簡単にできると思われる。

Boot Camp で Mac に Windows をインストールする方法 - Apple サポート

快適に使うためのBootCampの初期設定

1. スクロール方向を逆にする

  • ファイル名を指定して実行、の項目でregeditを入力し、「レジストリ エディター」を開く。
  • コンピューター¥HKEY_LOCAL_MACHINE¥SYSTEM¥ControlSet001¥Enum¥HID¥VID_¥¥Device Parameters のディレクトリから自分の使っているマウスホイールに割り当てられているIDのものを探し、FlipFlopWheel項目をクリックして、「DWORD(32ビット)値の編集」ウィンドウが表示されたら、「値のデータ」を「1」に変更し、「OK」をクリックする。
  • 再起動する。

詳しくは

Boot Camp上のWindows - スクロールをナチュラル(逆)方向に変更 - PC設定のカルマ を見てください。

2. commandキーをcontrolキーにする

初期設定のままだとcommandキーにwindowsキーが割り当てられて使いづらい。

Windows Registry Editor Version 5.00

[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Keyboard Layout]
"Scancode Map"=hex:00,00,00,00,00,00,00,00,02,00,00,00,1d,00,5b,e0,00,00,00,00

これを *.reg 拡張子でデスクトップなどに適当に保存し、レギストリエディタでImport してから再起動すると反映される。

詳しくは

MacbookProのBootcampで、CommandボタンをCtrlキーにする方法 - のびっこ日記 を見てください。

3. 日本語- Roma字の切り替えをcommand + space キーで行えるようにする

下記サイトを参考に、Microsoft IME 詳細プロパティにて、「Ctrl+SPACE」に『IME オン/オフ』(もしくは変換モード切替)を設定すればよい。

[Mac] BootCampなWindows 7を快適に操作するためにした設定 & やったこと | Tools 4 Hack

## ターミナルどこ?

Windows用の仮想ターミナルは、コマンドプロンプトという名前になる。

vim 使えるようにしたい

初期状態で入っていないので取ってくる。 www.kaoriya.net

覚えておくべきコマンド

  • dir : ls
  • del: rm
  • move: mv ( rename, move )
  • xcopy : cp

WebSocketとはなにか

https://www.pubnub.com/wp-content/uploads/2013/09/WebSockets3.png

WebSocket(ウェブソケット)は、コンピュータ・ネットワーク用の通信規格の1つ。

XMLHttpRequest(いわゆるAjax)の欠点を解決する技術として開発された。Ajaxの弱点というのは、クライアントからサーバーに通信できても、サーバーからクライアントに通信を行う方法がなかったこと。サーバ、クライアントの双方向で通信できる双方向通信を実現するための技術規格として生まれたもの。クライアントで変更があったとき(チャットに自分が投稿した時)、サーバーで変更があった時(チャットで他のユーザーが投稿したメッセージを受け取った時)、この両方を検知してリアルタイムで反映してくれる。

WebSocketでは、サーバとクライアントが一度コネクションを行った後は、必要な通信を全てそのコネクション上で専用のプロトコルを用いて行う。つまり、最初の通信の確立じたいはHTTPプロトコルだが、そのご別のWebSocket専用のプロトコルで通信する。通信時に指定するURLは「http://www.sample.com/」ではなく,「⁠ws://www.sample.com/」の形式である。(80ポートではなく、443ポートでの通信を行う時はwss://になる)

http://labs.opentone.co.jp/wp-content/uploads/2013/04/2522_fig02.png 画像は 【HTML5】WebSocketとJavaサンプルプログラムのご紹介 | Opentone Labs. より

従来の手法に比べると、新たなコネクションを張ることがなくなる・HTTPコネクションとは異なる軽量プロトコルを使うなどの理由により通信ロスが減る、といったメリットがある。

WebSocketの接続を確立するために、クライアント側はまず ハンドシェイク要求 を送る。そして、サーバー側はハンドシェイク応答を返す。

例:

ウェブブラウザが以下の要求をサーバー側に送る:

GET /chat HTTP/1.1
Host: server.example.com
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==
Origin: http://example.com
Sec-WebSocket-Protocol: chat, superchat
Sec-WebSocket-Version: 13

サーバー側は以下の応答を返す。

HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=
Sec-WebSocket-Protocol: chat

リクエストとレスポンス・ヘッダの中で重要なポイントは大きく4つ。

  1. WebSocketの接続先を指定する「Host」
  2. ハンドシェイク応答を得るための「Sec-WebSocket-Key」
  3. クライアントとのコネクションを維持するための「Sec-WebSocket-Accept」
  4. WebSocketのバージョンを指定する「Sec-WebSocket-Version」

以上のリクエストとレスポンス・ヘッダにより、WebSocketによる接続が確立される。

参考

WebSocket - Wikipedia

qiita.com

次回は、実際にWebsocketでチャットアプリを作って見たいと思う。

3Dプリンタから4Dプリンタまで。デジタルファブリケーションについて調べてみた

暦本先生の授業を受けて、気になったので調べてみた。 まずは総務省サイトより引用。

デジタルファブリケーションとは、デジタルデータをもとに創造物を制作する技術のことである。3Dスキャナーや3D CADなどの測定機械により、自分のアイデアや個人の身体データ等をデジタルデータ化した上で、そのようなデジタルデータを3Dプリンターやレーザーカッターなどのデジタル工作機械で読み込んで造形する

総務省|平成28年版 情報通信白書|デジタルファブリケーション

http://www.soumu.go.jp/johotsusintokei/whitepaper/ja/h28/image/n4103070.png

デジタルファブリケーションによるメリットは複数あるが、第一にはこれまでの製造技術では作製困難なものが作製できる点があげられる。加えて、個人レベルでの新しいものづくりが可能となり、これまでものをつくる行為に携わっていない人々のものづくりへの参画や、「Fab Lab(ファブラボ)」と呼ばれるデジタルファブリケーション機器が設置された施設を使うことで、組織に属さずとも高度な工作機器を使用した自由なものづくりが可能となり、新しいイノベーション、新しい経済、新しい働き方が生まれると期待されている。

  • 今まで作るのが難しかったものが作れる…(1)
  • 組織に属していなくてもものづくりができる…(2)

のがポイント。

(1)に関して彫刻家・名和晃平氏の作品がよく挙げられる。名和氏は作品制作に3Dプリンターを利用している。 http://sandwich-cpca.net/img/common/main-20.jpg

(2)に関して、「パーソナル・ファブリケーション」という考え方を紹介したい。

”パーソナル・ファブリケーション”は簡単に説明すると「ほぼなんでも(自分で)作ろう、ほぼなんでもプリントしよう」的な考え方。その活動は1998年からMITでスタートしていて、現在のテクノロジーによって開発された3Dプリンタや切削機など、3Dプリンティングの技術を駆使して自分が欲しいハードウェアは自分で作ろうという試みだ。その活動は1998年からMITでスタートしていて、現在のテクノロジーによって開発された3Dプリンタや切削機など、3Dプリンティングの技術を駆使して自分が欲しいハードウェアは自分で作ろうという試みだ。

CBCNET » なんでも自分たちで作ろう、パーソナル・ファブリケーションの実践 “Fabrication Laboratory” at DHUB, Barcelona

医療分野への応用

医療分野は、3Dプリンターが参入したことで技術開発がすさまじいスピードで進んだ分野である。人工物で作られるため、非常に良い状態で包装・輸送・保管が可能であり、発展途上国の医療も変えるとされている。

人口骨

欠損した骨を人口骨で補う技術も実用段階にある。ベンチャー企業NEXT21(東京都文京区)が東京大学のチームと共同開発した人工骨プリンター「CT-Bone」は骨の欠損部を0.1mm単位の高い精度で再現できる。人工骨は手術前に用意できる。そのため、これまで6~8時間かかっていた手術は2時間で済むようになり、施術中の患者の負担を大きく軽減できる。 さて、ここまで紹介した技術革新は医師の負担を軽減するなどの効果は見込むことができる。こぼれ落ちる命を救うこともあるだろう。だが、技術として見たとき、それだけでは“イノベーション”たりえない。実はCT-Boneが業界に与えた最大の衝撃は「人間の骨のように、元の骨にくっつき同化して骨代謝に取り込まれる」ことだった。「CT-Boneは移植後に骨代謝(こつたいしゃ)をします。骨代謝とは古い骨が新しい骨に生まれ変わる新陳代謝のこと。人は18か月のサイクルで全身の骨が入れ替わります。これまでの人工骨は焼成して作られた、瀬戸物のようなものでした。そうした人工骨を移植した患者は最終的に皮膚から異物として皮膚から露出してしまう。CT-Boneの素材は代謝循環に乗せられるので自分の骨になるのです。」

骨の元になる原料を固めたブロックを焼却して工作機械で削り出す方法で作られていた。それが、原料を積層しながら形成するプリンター技術なら焼かずに人工骨を作ることが可能になったのだ。プリント技術によってもたらされた利点は他にもある。

3Dプリンターは内部構造を再現できるため、骨髄が通る中空も再現することができます。人工骨に骨髄が流れることで自分の骨として定着。移植して半年後には骨代謝で自分の骨に変わっています。ちなみに人工骨の原料は2001年に独自に開発をしたリン酸カルシウムを再結晶化させたもの(Ca欠損ハイドロオキシアパタイト)です」このCa欠損ハイドロオキシアパタイトは人間の骨と同じ成分なので移植して患者自身の骨に一体化しやすい。

掲載元:(3Dプリンターで作る人工骨の技術革新。欠損した骨が再生可能に | ハーバービジネスオンライン)

義手

義手・義足など需要の限られた製品もプリント技術を使えば金型を作る必要がないため、今後低コストでの実用化が見込める。 従来、特に子供は、成長にともない、義手義足のまめな作成が必要であるため、大きな負担を強いられていた。

さらには、

 MITのHugh Herrをはじめとするイノベーターたちによって、駆動システム、内蔵センサー、関節の自然な動きを自動化する高度なアルゴリズム等を組み合わせた新しい技術が開発されている。人工装具の予測的動作によって、使用者は装置の制御について深く考える必要がなくなる。近いうちに、人工装具はさらに滑らかで自然な動きをするようになり、使用者は脳やタッチ入力システムによる直接操作によって装置を制御できるようになるだろう。

3Dプリントが可能にする誰もが義肢を設計する未来 | TechCrunch Japan

歯の矯正

自分で3Dプリンタで矯正マウスピースを作って格安で歯の矯正に成功した猛者もいるみたいだ。

メイカーズムーブメントと、オープンソースによる効果

デジタルファブリケーションの効用は、

  • 今まで作るのが難しかったものが作れる…(1)
  • 組織に属していなくてもものづくりができる…(2)

にとどまらない。3Dデータ共有サイト「Thingiverse」のようなプラットフォームによって、クリエータ同士の相乗効果が生まれる。

www.thingiverse.com

オープンソースハードウェア」の流れが生まれることで、ソフトウェアのオープンソースの世界で、firefox, mysql, linux, wordpress… といった素晴らしいプロダクトが生み出されたように、イノベーションが加速すると考えられる。

3Dプリンターマイクロコンピュータの登場により、個人でもIoTなどの製造が可能となってきた。この動きを「メイカーズムーブメント」という。個人が作ったプロダクトは、まるで写真を共有するかのように、オンラインのコミュニティで共有されている。 オープンソースハードウェアとは、ハードウェアの設計(3D CADデータ等)、エレクトロニクスの設計(基板上の部品配置、回路図)、ソフトウェアなどの情報を無償で公開することを指す。これらのデータと、3Dプリンターなどの製造機械があれば、製品を自分で作ることができる。さらに自分で変更を加えることもできる。

今から知っておきたい、注目のオープンハードウェア10選 | freshtrax | デザイン会社 btrax ブログ

なんと、3Dプリンタ3Dプリンタで製造するデータもシェアされている。

www.kickstarter.com

ハードウェアがプログラムできるということ — 4Dプリンタ

4D, と言われても戸惑うかもしれない。3Dプリンタのメリットを生かし、素材や電子回路の埋め込みによって、制作後の動きをデザインすることを4Dプリンティングと言うようだ。

vimeo.com

MITのスカイラー・ティビッツが米国時間26日に公開した新たな技術。水のなかで形状が変化していくひも状の物体。この技術の重要な点は、3Dプリンターをつかって制作された物体がその後、自己適応的に変形できるようになっているところだ。つまり、3Dプリンターの利用自体は創造プロセス全体の中間点に過ぎないということになる。「何かを設計して、それを3Dプリントすると、その物体は進化する。これは、物体に自然の知性を埋め込むようなものです」とティビッツ氏は話す。

電子の世界をリアルにするということ

3Dプリンタの行う、電子の世界をリアルにすることの凄さを伝えてくれるのが、MIT石井先生の研究グループである「Tangible Media Group」の以下の動画だ。

Tangible Media Group

リモートでりんごを動かしたり

f:id:serendipity4u:20170628000339p:plain

数式を立体的なグラフにしてくれたり

f:id:serendipity4u:20170628000606p:plain

物体を作り出しながら高さを調整したり

f:id:serendipity4u:20170628001055p:plain

数年後、プロダクトデザインはPCで設計図を書きながらするものではなく 会議室でワイワイしながら色を変え高さを変え完成品まで作ってしまうものになるのかもしれない。 ファストファッションブランドは設計図だけを売るようになるのかもしれない。

Wordpressで独自のユーザー項目を追加し表示する

https://s.w.org/images/backgrounds/wordpress-bg-medblue.png

ユーザー項目の追加

functions.phpにて、

$wb['フィールド名'] = '表示名';

の規則に従い、追加していく。

// ユーザープロフィールの項目のカスタマイズ
function my_user_meta($wb)
{
    //項目の追加
    $wb['twitter'] = 'twitter';
    $wb['facebook'] = 'facebook';
    $wb['position'] = '役職';

    return $wb;
}
add_filter('user_contactmethods', 'my_user_meta'); //追加するには、user_contactmethods フィルターフックを使用。user_contactmethodsという文言は変えないこと!

ユーザー項目の表示

「the_author_meta」というテンプレートタグを利用する。 このタグをループの中で使った場合、ユーザー ID を指定する必要はなく、表示されるデータは現在の投稿の作成者のものになる。

<?php echo get_the_author_meta( 'twitter' ); ?>

ループの外で使う場合、ユーザー ID を指定する必要がある。

<?php echo get_the_author_meta( 'twitter', $userID ); ?>

デフォルトのユーザー項目のフィールド名

既存のユーザー項目のフィールド名を参考までにあげておく。 (例: <?php the_author_meta( 'user_email', $userID ); ?>)

user_login
user_pass
user_nicename
user_email
user_url
user_registered
user_activation_key
user_status
display_name
nickname
first_name
last_name
description
jabber
aim
yim
user_level
user_firstname
user_lastname
user_description
rich_editing
comment_shortcuts
admin_color
plugins_per_page
plugins_last_view
ID

the_author_meta() は wp-includes/author-template.php 内で定義されている。

表示しているテンプレートがどこかわからない時

ja.wordpress.org

で表示してみる。

参考にしたサイト

テンプレートタグ/the author meta - WordPress Codex 日本語版

whitebear-seo.com

wordpressの子テーマのheader.phpに独自jsファイルを挿入する(例:smooth scroll ライブラリ)

https://s.w.org/images/backgrounds/wordpress-bg-medblue.png

header.php に, smooth_scroll.js を挿入する

smooth_scroll.jsは、 jQueryに依存せずに、 スクロール速度や加速度を制御できたり、 コールバック関数を作れたりする素敵なライブラリです。

子テーマ内の、header.phpファイルのheadタグにて、

<script type="text/javascript" src="<?php echo get_stylesheet_directory_uri(); ?>/追加したjsファイル名"></script>

としてあげます。

この場合、

<script type="text/javascript" src="<?php echo get_stylesheet_directory_uri(); ?>/smooth_scroll.js"></script>

になります。

smooth scroll を動かす

smooth scroll のoption を指定し、

smoothScroll.init({ Â speed: 300 , 
    updateURL: false, 
    easing: 'easeInOutCubic' 
}) ;

動かしたいファイルで、 クリックをリッスンしたい要素にdata-scroll属性を付与してあげ、

<a href="#gotoEnglish" data-scroll> &gt;&gt; English Version </a>

... 省略

<div id='gotoEnglish'>
... ここに飛ばしたい
</div>

飛ばしたい先にidを付与してあげればOKです。

参考

motoshige.net

javascriptのスコープとprototypeについて

スコープ

JavaScript には、グローバルとローカルの 2 つのスコープがあります。 関数定義の外部で宣言された変数はグローバル変数になり、プログラム内のどこからでも値の参照や変更を行うことができます。 関数定義内で宣言された変数はローカル変数になります。 ローカル変数は、関数が実行されるたびに作成され破棄されます。関数の外部のコードからローカル変数にアクセスすることはできません。

JavaScript では、ブロック スコープ変数の特殊な場合を除いて、(中かっこで囲んで ({…}) 新しいスコープを定義する) ブロック スコープはサポートしていません。 ( ただし、Internet Explorer 11 では、ブロック スコープ変数である let および const のサポートが導入されています。)

var hoge = "global";

function showHoge(){
  print(hoge); //undefined
  var hoge = "local";
  print(hoge); //local
  return hoge;
}

print(showHoge()); //local
print(hoge); //global

prototype

prototype は関数のプロパティ、およびコンストラクター関数によって作成されるオブジェクトのプロパティです。

JavaScriptオブジェクト指向言語。クラスという概念はないため、擬似的なクラスの表現を使ったパターンがあります。

私はクラスとインスタンスの関係はたいやきとたいやきの型で考えるのが好きなので、この場合も、Taiyaki(); というクラス(的なもの)を作ってみたいと思います。

function Taiyaki() {} // たい焼きクラスを宣言
Taiyaki.prototype.nakami= function() { // prototypeの機能としてnakamiを作る
  console.log('あんこ');
};

var taiyaki = new Taiyaki();
taiyaki.nakami(); //'あんこ';

prototype プロパティを使用すると、既に作成されているオブジェクト にもプロパティおよびメソッドを追加できます。

function Taiyaki(nakami) {
    this.nakami = nakami;
}
var taiyaki = new Taiyaki('あんこ');
Taiyaki.prototype.price = 300;
var taiyaki_price = taiyaki.price;

参考

変数のスコープ (JavaScript) qiita.com

今日からfloatは使うな!便利すぎるflexボックスについてまとめてみる

flexプロパティは、横並びの要素に対してとても便利なプロパティです。float, clearを使っていた時と比べ、コードが1/3くらいになるというのが体感値です。要素を逆並べするなど、float, clearのセットでは実現できないような挙動もシンプルに実現できます。

そんなflexプロパティの使い方から応用までまとめました。 基本的には以下の公式ドキュメントの引用になります(当記事執筆時)。

Flexible box ("Flexbox") layout in Internet Explorer 10 (Windows)

Flexbox レイアウトは、複雑な Web ページをレイアウトすることを目的とし、画面やブラウザー ウィンドウのサイズがさまざまに変化する場合にも要素の相対的な位置とサイズを一定に保つ場合に、特に役立ちます。位置とサイズを正しく設定するのが難しいフロートへの依存を軽減できます。

Flexbox レイアウトは、ボックスのサイズを定義するときに利用可能な領域を考慮することで、相対サイズと相対配置を有効にします。たとえば、ブラウザー ウィンドウ内の余分な空白を、複数の子要素にそのサイズに応じて均等に分配し、それらの子要素をコンテナーとなるブロックの中央に配置することができます。

flexbox レイアウトを使うと、次の作業が可能になる

  • 異なるサイズの画面やブラウザー ウィンドウを使用した際にも — 流動的で、しかも互いに相対的な位置とサイズを維持する複数の要素 (イメージ、コントロールなど) で構成されるレイアウトを構築する。 一連の要素のレイアウト軸 (水平または垂直) に並行する余白を、指定した要素のサイズの増加に比例して割り当てる方法を指定する。
  • 一連の要素のレイアウト軸に並行する余白を、一連の要素の前後または間に割り当てる方法を指定する。 左右に並べて配置されたボタンの上下の余白など、要素の周りにある、要素のレイアウト軸に対して垂直な余白の形を指定する。
  • ページ内に要素を配置する方向を制御する — たとえば、上から下、左から右、右から左、下から上など。 ドキュメント オブジェクト モデル (DOM) で指定されている順序とは異なる順序で、画面上の要素を並べ替える。
プロパティ説明

-ms-flex-direction

オブジェクトのすべての子要素のレイアウトの方向を指定します。

このプロパティに指定できる値は、次のキーワードです。

row

これは初期値です。子要素は、ソース ドキュメントで宣言されているのと同じ順序 (左から右) で表示されます。

-ms-box-orient:horizontal の例
column

子要素は、ソース ドキュメントで宣言されているのと同じ順序 (上から下) で表示されます。

-ms-box-orient:vertical の例
row-reverse

子要素は、ソース ドキュメントで宣言されているのと逆の順序 (右から左) で表示されます。

-ms-box-direction:normal の例
column-reverse

子要素は、ソース ドキュメントで宣言されているのと逆の順序 (下から上) で表示されます。

inherit

子要素は、親要素のこのプロパティの計算値と同じ順序で表示されます。

適用の仕方

1. flexコンテナを作る

.flex{
  display: -ms-flexbox;
  display: flex;
  display: -webkit-flex;
}

flexbox レイアウトを有効にするには、最初に flexbox コンテナーを作成する必要があります。

そうするには、要素の display プロパティを “-ms-flexbox” (ブロック レベルの flexbox コンテナーの場合) または “-ms-inline-flexbox” (インライン flexbox コンテナーの場合) に設定します。

(CSS 可変ボックス レイアウト モジュールの草案は暫定版であるため、この値を始め、このセクションのプロパティを Internet Explorer 10 と、Windows 8JavaScript を使った Windows ストア アプリで使うときは、いずれも Microsoft 固有のベンダー プレフィックス “-ms-” を付ける必要があります。)

2. flexbox の方向の設定

プロパティ説明

-ms-flex-direction

オブジェクトのすべての子要素のレイアウトの方向を指定します。

このプロパティに指定できる値は、次のキーワードです。

row

これは初期値です。子要素は、ソース ドキュメントで宣言されているのと同じ順序 (左から右) で表示されます。

-ms-box-orient:horizontal の例
column

子要素は、ソース ドキュメントで宣言されているのと同じ順序 (上から下) で表示されます。

-ms-box-orient:vertical の例
row-reverse

子要素は、ソース ドキュメントで宣言されているのと逆の順序 (右から左) で表示されます。

-ms-box-direction:normal の例
column-reverse

子要素は、ソース ドキュメントで宣言されているのと逆の順序 (下から上) で表示されます。

inherit

子要素は、親要素のこのプロパティの計算値と同じ順序で表示されます。

3. flexboxの子要素どうしの余白の配分の指定

プロパティ説明

-ms-flex-pack

オブジェクトの子要素間の余白 (-ms-flex-direction プロパティで定義された軸の方向の余白) の分配方法を指定します。

このプロパティに指定できる値は、次のキーワードです。これらのキーワードは writing-mode に依存することに注意してください。親要素と子要素の開始エッジと終了エッジはレイアウト方向に依存します。たとえば、開始エッジは、左から右のレイアウトの場合は親要素の左端、上から下のレイアウトの場合は上端のようになります。同様に、子要素の終了エッジは、左から右のレイアウトの場合は右端、上から下のレイアウトの場合は下端のようになります。

start

これは初期値です。レイアウト軸の方向に沿って、最初の子要素の開始エッジが親要素の開始位置に揃えて配置され、以降の子要素の開始エッジが前の子要素の終了エッジに揃えて配置されていきます。レイアウト軸の方向のすべての余白が、レイアウト軸方向の末尾に配置されます。

-ms-box-pack:start の例
end

レイアウト軸の方向に沿って、最初の子要素の終了エッジが親要素の終了位置に揃えて配置され、以降の子要素の終了エッジが前の子要素の開始エッジに揃えて配置されていきます。レイアウト軸の方向のすべての余白が、レイアウト軸方向の先頭に配置されます。

-ms-box-pack:end の例
center

start キーワードや end キーワードと同じようにすべての子要素が端を揃えて配置されますが、それらの子要素のグループが親要素の開始エッジと終了エッジの間の中央の位置に配置されます。すべての余白が最初の子要素の前と最後の子要素の後に均等に分配されます。

-ms-box-pack:center の例
justify

最初の子要素の開始エッジが親要素の開始位置に揃えて配置され、最後の子要素の終了エッジが親ボックスの終了位置に揃えて配置されます。残りのすべての子要素は、最初の子要素と最後の子要素の間に、レイアウト軸の方向の余白が子要素間で均等に分配されるようにして配置されます。

-ms-box-pack:justify の例

応用

  • クリックしたらそのパネルが大きくなるエフェクト

Flexアイテムの「伸びる」倍率を示す、flex-growをhoverで発火させることによって実現させる。

 &:hover{
      flex-grow: 1.8;
      transition: flex 0.2s;
  }

Flex Selection #2 CSS Hover Effect

f:id:serendipity4u:20170619223727p:plain

f:id:serendipity4u:20170619223758p:plain

javascriptでDOMを操ろう. バックエンドエンジニアのためのDOM操作関連スニペットまとめ

http://org-rabo.com/wp-content/uploads/2016/06/javascriptlogo.png

バックエンドエンジニアがjavascriptを学ぶメリットはたくさんあります。javascriptメソッドを活用すると、数十行かかっていた挙動がjavascriptの1コードで達成できる、といったことも。「JavaScriptを1行書くだけで、バックエンド専業エンジニアが不要になるAPI」なんてサービスもあるくらいですから。バックエンドの解決策とフロントエンドの解決策、その2つの選択肢から選べるエンジニアになるべく、とりわけ需要の高いと思われる、Webページの要素の操作と、マウスとの連動に絞って、まとめます。

バックエンドエンジニアだって、lets' javascript!

DOM(Document Object Model)とは

文書オブジェクトモデル(DOM)とは、HTML文書およびXML文書のためのアプリケーション=プログラミング=インターフェイス(API)である。 これは、文書の論理的構造や、文書へのアクセスや操作の方法を定義するものである。 DOM仕様書においては「文書」という用語は広い意味で使われる

DOMとは何か

ざっくりいうと、文書の論理構造を示すもので、木構造になっています。

http://courses.cs.washington.edu/courses/cse190m/10su/lectures/slides/images/dom_tree.gif

http://courses.cs.washington.edu/courses/cse190m/10su/lectures/slides/images/dom_tree.gif

DOMツリーのひとつひとつの要素を、ノードと言います。上の図の、上位のノードが共通な要素をsibling nodes(きょうだいノード) といい、直接上位にあるノードをparent nodeといいます。 ノードは、以下のようなプロパティーを持っていて、siblingやparentを簡単にとってこれます。

  • firstChild, lastChild
  • childNodes
  • nextSibling, previousSibling
  • parentNode

childNodes.length メソッドで、何個のノードを持っているか知ることができる。

要素を取得してみる: getElementBy…

  • IDで取得する: document.getElementById(id);

  • classで指定する: document.getElementByClassName('container wrapper');  ByClassではなくByClassNameであることに注意. 取得できるのはHTMLCollectionという、配列と似た構造のデータ. 半角スペースで区切って、複数のクラスを指定できる。

  • Tagで指定する: document.getElementsByTagName("div") 配列で取得される.

  • 画像を全て取得する: document.images;

  • CSSセレクタで一致する最初のオブジェクトを取得する: document.querySelector('#wrapper .article h1'); //最初の一つを取得

  • CSSセレクタで一致するすべてのオブジェクトを取得する: document.querySelectorAll('a'); //すべて取得

要素を取得して、テキストを書き換える

テキストのみの書き換えならtextContent

 document.getElementById("str").textContent="テキストの書換え";

htmlの書き換えならinnerHTML

 document.getElementById("str").innerHTML="<b>タグ</b>を含む書換え";

マウスアクション

参考: 【JavaScript】ウェブサイト制作の際によく使うイベントまとめ | Web制作会社スタイル

ある要素をクリックしたら: addEventListener( ‘click’ , {})

var element = document.getElementById("ID名");
element.addEventListener("click",function(event){
//処理の内容
});

クリックした位置を取得する(絶対座標): e.pageX, e.pageY

Webサイトのどの位置をクリックしたか取得する。

// マウスイベントを設定
document.body.addEventListener( "click", function( e ) {
    // マウス位置を取得する
    var mouseX = e.pageX ;  // X座標
    var mouseY = e.pageY ;  // Y座標
} ) ;

ある要素における、クリックした位置を取得する(相対座標) : getBoundingClientRect()

target というIDの付与された要素の左上から、マウスまでの距離を取得する。

// マウスイベントを設定
document.getElementById( "target" ).addEventListener( "click", function( e ) {
    // マウス位置を取得する
    var mouseX = e.pageX ;  // X座標
    var mouseY = e.pageY ;  // Y座標

    // 要素の位置を取得
    var element = document.getElementById( "target" ) ;
    var rect = element.getBoundingClientRect() ;

    // 要素の位置座標を計算
    var positionX = rect.left + window.pageXOffset ;    // 要素のX座標
    var positionY = rect.top + window.pageYOffset ; // 要素のY座標

    // 要素の左上からの距離を計算
    var offsetX = mouseX - positionX ;
    var offsetY = mouseY - positionY ;
} ) ;

プルダウンを選択したら (onchange関数)

<form action="#">
    <select onchange="alert(this.options[this.options.selectedIndex].text)">
        <option value="">▼選択してください</option>
        <option value="apple">りんご</option>
        <option value="banana">バナナ</option>
    </select>
</form>

要素を選択したら:onselect

こんな感じでマウスハイライトしたら、発火するイベント。 f:id:serendipity4u:20170619145616p:plain

 <textarea cols="60" rows="2" onselect="alert('テキストが選択されました')">
このテキストを選択してみて下さい
    </textarea>

どこかのキーが押されたら: addEventListener(‘keydown’ , {})

document.body.addEventListener("keydown",function(event){
//処理の内容
});

要素からマウスが外れたら: addEventListener(‘mouseout’, {})

var element = document.getElementById("ID名");
element.addEventListener("mouseout",function(event){
//処理の内容
});

要素にマウスを載せたら:

要素が右クリックされたら: addEventListener(‘contextmenu’, {})

var element = document.getElementById("ID名");
element.addEventListener("contextmenu",function(event){
//処理の内容
});

要素がカット/コピーされたら: addEventListener(‘cut’, {})

var element = document.getElementById("ID名");
element.addEventListener("cut",function(event){
//処理の内容
});

DOMの構築が完了したら: addEventListener(‘DOMContentLoaded’, {})

window.addEventListener("DOMContentLoaded",function(event){
//処理の内容
});

頻出表現

タイマー関数 setInterval( );

決まった時間ごとに()の中の関数を繰り返し実行する。他にも、JavaScriptのタイマー関数には「setTimeout」があり、「setInterval」と違って、決まった時間が来たら一度だけ()の中の関数を実行する。

setInterval(関数function, 一定時間の指定[, 引数1, 引数2, …])

var count = 0;
      var countup = function(){
        console.log(count++); // countup関数を用意
      } 

setInterval(countup, 1000); // 1000ミリ秒ごとにcountup()を実行。

Webページのスコープ内で実行されるscriptを注入する: createElement(‘script’)

// <script>エレメントを作って注入する。
var script = document.createElement("script");
script.textContent = "hoge();"; // 実行したい処理
document.body.appendChild(script); 

オブジェクトの存在確認 : undefined

if (typeof a === "undefined") {
  alert('a = undefined');
}

jsonシリアライズ: parse, stringify

JSONフォーマットの文字列は、見た目はJSのオブジェクト同じに見えても実際のフォーマットが異なるため、JSONフォーマットで受け取ったオブジェクトはJSオブジェクトにデシリアライズする必要がある。

  • jsonをjsハッシュにするとき:JSON.parse(getData);
  • js ハッシュから json にするとき:JSON.stringify(localObject);

参考

eng-entrance.com

github.com

courses.cs.washington.edu

phpjavascriptroom.com

コードと公式ドキュメントから読む:Chrome拡張機能開発、ゼロから解説

f:id:serendipity4u:20170618125453j:plain

Chrome拡張機能開発のイロハからマネタイズモデルまで説明します。

Chrome 拡張機能を利用するメリット

拡張機能にしか提供されていないChromeのネイティブのAPI群を利用してアプリケーションが開発・連携できるところ。 例えば、Chrome Tab API で開かれているタブのタイトルを取得したり、開かれているページのDOMを取得するなど。

Chrome拡張機能の構成

ファイル構成から見るより、manifest.jsonから見る方がわかりやすいので、次はmanifest.jsonを紹介する。

manifest.json の中身

それぞれの意味の説明は後述する。

{
  "manifest_version": 2,
  "name": "Sample Extension",
  "description": "This extension is sample.",
  "version": "1.0",
  "icons": {
    "16": "images/icon/icon_16.png",
    "48": "images/icon/icon_48.png",
    "128": "images/icon/icon_128.png"
  },
  "background": { // 解説
    "scripts": [
      "js/background.js"
    ],
    "persistent": false
  },
  "browser_action": {  // 解説
    "default_icon": {
      "19": "images/icon/icon_19.png",
      "38": "images/icon/icon_38.png"
    },
    "default_title": "Sample Extension",
    "default_popup": "popup.html" // 解説
  },
  "content_scripts": [ // 解説
    {
      "matches": [ // 解説
        "http://*/*",
        "https://*/*"
      ],
      "css": ["css/sample.css"],
      "js": ["js/content_scripts/sample.js"]
    }
  ],
  "permissions": [ // 解説
    "tabs",
    "https://*/*",
    "http://*/*",
    "storage"
  ]
}

上記は最小構成に近いが、公式ドキュメントによると以下の項目がある。

{
  // Required
  "manifest_version": 2,
  "name": "My Extension",
  "version": "versionString",

  // Recommended
  "default_locale": "en",
  "description": "A plain text description",
  "icons": {...},

  // Pick one (or none)
  "browser_action": {...},           
  "page_action": {...},

  // Optional
  "author": ...,
  "automation": ...,
  "background": {
    // Recommended
    "persistent": false
  },
  "background_page": ...,
  "chrome_settings_overrides": {...},
  "chrome_ui_overrides": {
    "bookmarks_ui": {
      "remove_bookmark_shortcut": true,
      "remove_button": true
    }
  },
  "chrome_url_overrides": {...},
  "commands": {...},
  "content_capabilities": ...,
  "content_scripts": [{...}],
  "content_security_policy": "policyString",
  "converted_from_user_script": ...,
  "current_locale": ...,
  "devtools_page": "devtools.html",
  "event_rules": [{...}],
  "externally_connectable": {
    "matches": ["*://*.example.com/*"]
  },
  "file_browser_handlers": [...],
  "file_system_provider_capabilities": {
    "configurable": true,
    "multiple_mounts": true,
    "source": "network"
  },
  "homepage_url": "http://path/to/homepage",
  "import": [{"id": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"}],
  "incognito": "spanning, split, or not_allowed",
  "input_components": ...,
  "key": "publicKey",
  "minimum_chrome_version": "versionString",
  "nacl_modules": [...],
  "oauth2": ...,
  "offline_enabled": true,
  "omnibox": {
    "keyword": "aString"
  },
  "optional_permissions": ["tabs"],
  "options_page": "options.html",
  "options_ui": {
    "chrome_style": true,
    "page": "options.html"
  },
  "permissions": ["tabs"],
  "platforms": ...,
  "plugins": [...],
  "requirements": {...},
  "sandbox": [...],
  "short_name": "Short Name",
  "signature": ...,
  "spellcheck": ...,
  "storage": {
    "managed_schema": "schema.json"
  },
  "system_indicator": ...,
  "tts_engine": {...},
  "update_url": "http://path/to/updateInfo.xml",
  "version_name": "aString",
  "web_accessible_resources": [...]
}

Browser Action

Browser actionとは、Chrome拡張機能の3つのうちの1つで、もっともベーシックなタイプである、ツールバー右に並んで表示される拡張機能のことを指す。

f:id:serendipity4u:20170618100209p:plain

これらのアイコンをクリックすると、例えば下図のようにポップアップが表示されるが、

f:id:serendipity4u:20170618100312p:plain

このポップアップの内容は

  "browser_action": {
    "default_icon": {
      "19": "images/icon/icon_19.png",
      "38": "images/icon/icon_38.png"
    },
    "default_title": "Sample Extension",
    "default_popup": "popup.html"
  },

で定義されているというわけだ。 popup.htmlは、 例えばこのような形になっている。

<!DOCTYPE html>
<html lang="ja">
  <head>
    <meta charset="utf-8">
    <title>Sample Extension</title>
    <link rel="stylesheet" href="css/popup.css" type="text/css">
    <script src="js/jquery.js"></script>
    <script src="js/popup.js"></script>
  </head>
  <body'>
    <p>Title: <span id="title"></span></p>
  </body>
</html>

このように、外部スタイルシートを読み込んだり、普通のWebページ制作と何ら変わらない。

Content Script

Chromeで開いているWebページにおいて動作させる」cssjavascriptを定義する。 どうしてこれが必要なのかというと、 popup.html 上で実行するjavascriptも、backgroundで実行するjavascriptも、直接的には開いているページのDOM 要素にアクセスできないからだ。なぜかというと、既存のWebページと拡張機能が注入するjsファイルなどとのコンフリクトを避けるためだ(jQueryの2重読み込みなど)。 一部のChrome Tab API を利用できない制限があるのだが、これはbackgroundに処理を渡すことで、解決できる。 また、おそらくセキュリティ上の理由から、ページ内で定義されている変数や関数にはアクセスができない。

"content_scripts": [ // 解説
    {
      "matches": [ // 解説
        "http://*/*",
        "https://*/*"
      ],
      "css": ["css/sample.css"],
      "js": ["js/content_scripts/sample.js"]
    }

このmatches は、常にExtensionを実行したいわけではないだろう、例えばpdfページとか、google.comでだけ動作させたいとか、localhostでは実行したくないとか、そういう需要もあるであろうという了解のもとにある項目で、content scriptを実行するURL条件を指定することができる。

公式ドキュメントでは

Required. Specifies which pages this content script will be injected into. See Match Patterns for more details on the syntax of these strings and Match patterns and globs for information on how to exclude URLs.

な項目として書かれている。

Background

Backgroupd Pagesはスクリプトを裏側でずっと実行できるようにするための仕組み。 Chromeが立ち上がっている間、ずっと実行しておきたい処理や、保持しておきたい状態を持つときに利用する。Content Script 内で、API利用制限(前述)があるので、backgroundに回したりする。

 "background": { // 解説
    "scripts": [
      "js/background.js"
    ],
    "persistent": false
  },

persistent: false は、 必要になったら動き、不必要になったら遊休状態になり、メモリが開放させる設定を表す。 通常、persistent: false 設定にする。このように常駐しないよう設定したものをevent ページと呼ぶ。 拡張機能によってはeventページでは難しいものもあるので、絶対にeventページにしなければいけないということはない。

Content Script から Backgroundに処理を回す

さて、Content Script には制限があるため、Backgroundに処理を渡すことがあると書いた。今から、その具体的な方法を説明する。

Content Scriptからメッセージを送信し、Backgroundに送る

メッセージを送るには、chrome.runtime.sendMessage API を利用する。

// Content Script で実行する js ファイル
chrome.runtime.sendMessage('Hellooo');

公式ドキュメントによると

chrome.runtime.sendMessage(string extensionId, any message, object options, function responseCallback)

で、レスポンスコールバックなどを定義できる。

chrome.runtime.sendMessage({ type: 'あいさつ', content: 'こんにちは〜', name: '花子'}, 
  function(response){
    console.log(response);
  } 
);

のように、ハッシュをメッセージとして送ることもできる。

BackgroundでContent Scriptから送信されたメッセージを受け取る

メッセージを受け取るには、chrome.runtime.onMessageAPI を利用してリスナーを設定する。

chrome.runtime.onMessage.addListener(function (message) {
  console.log(message);
});

リクエストの分岐によって処理を変えたい時は、

chrome.runtime.onMessage.addListener(
  function (request, sender, sendResponse) {
    switch (request.type) {
    case "あいさつ":
      // 処理
      break;
    case "その他":
      // 処理
      break;
    default:
      console.log("Error: Unkown request.")
      console.log(request);
    }
  }
);

のようにすれば実現できる。

公式ドキュメントでは

Fired when a message is sent from either an extension process (by runtime.sendMessage) or a content script (by tabs.sendMessage). ( runtime.SendMessage もしくは Content Script の tabs.sendMessage によってメッセージが送られてきた時に、発火する。)

とある。tabs.sendMessageについては後述する。

BackgroundからContent Script にメッセージを送信する

さて、Content Script から Backgroundにメッセージを送信することについて書いた。 それでは、逆はどうなるのか。 BackgroundからContent Scriptに処理を渡すとき、chromeにタブがたくさん開かれている場合は、どのタブにおけるContent Script か指定する必要がある。 タブを対象にメッセージを送る時は、 chrome.tabs.sendMessage API を利用する。chrome.tabs.sendMessage()の第一引数には、タブ固有のIDを指定する。

「今開いているタブ」に送ると指定する時

送信側で、chrome.tabs.query API を利用し、tabs という変数の中に今開いているタブの情報を配列で受け取って、tabs[0].id とすれば、今開いているタブのIDが取得できる。つまり、以下のようになる。

//backgroundのjs ( 送信側 )

chrome.tabs.query({active: true, currentWindow: true}, function(tabs) {
  chrome.tabs.sendMessage(tabs[0].id, {greeting: "hello"}, function(response) {
    console.log(response.farewell);
  });
});

content script側の受け取り方は、あとはbackgroundがcontent scriptからメッセージを受け取る時と同様で、 

chrome.runtime.onMessage.addListener(function (message) {
  console.log(message);
});

とonMessage.addListener を設定すればよい。

Tabで開いているWebページにhtmlを注入するには?

いくつか方法がありますが、もっとも直感的かつメンテが容易と思われたのが、iframeを使う方法です。

まず、embedded.htmlに、

<!DOCTYPE html>
<html><head>
    <title>Embedded Hello World</title>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8">

    <link href="test.css" rel="stylesheet" type="text/css">
    <script type="text/javascript" src="test.js"></script>
  </head><body>
    <p>Hello World!</p>
  </body>
</html>

など記述。

manifest.json

 "web_accessible_resources": ["embedded.html"]

と記載しアクセスできるようにします。 さらにmanifest.jsonに、iframeを注入するjsファイルも追加します(backgroundではなく、content scriptであることに注意)、

"content_scripts":          [ {
        "js":       [ "iframeInjector.js" ],

その(iframeInjector.jsの) 中身はこうです、

iframeInjector.js:

var iFrame  = document.createElement ("iframe");
iFrame.src  = chrome.extension.getURL ("embedded.htm");

document.body.insertBefore (iFrame, document.body.firstChild);

これで、ページトップにembedded.html が表示されるというわけです。 プログラマだけでなく、デザイナーに優しい作りですね。

出典はここです: javascript - Adding complex HTML using a Chrome content script - Stack Overflow

他のchrome拡張機能のソースを見る

構成を勉強したり、セキュリティ面で不要な通信などが行われていないか調べるため、利用している他人の作ったchrome拡張のコードを見たいという場合、わざわざインストールしなくても、ソースコードを見ることができる。

chrome.google.com

この拡張機能を使うと、chrome 拡張ストアで、詳細ページを開くだけで、ソースコードを見ることができるようになる。

Chrome 拡張のマネタイズモデル

さて、chrome拡張開発者たちは、楽しい以外にどんなインセンティブを持っているのか。

1) 広告表示で、マネタイズ

gigazine.net

ポリシー内容としては、
・挙動はユーザーが見て明らかであること
・広告はいずれも何の拡張機能が表示させているものなのか明らかにすること
・本来表示されている広告や、ウェブサイトの機能を妨害しないこと
と定められています。
また、表示させる広告については
・「Chrome Web Store Developer Terms」を破らないこと
・設定によって消せるか、拡張機能やアプリを削除した際に一緒に消えること
・システムメッセージや警告を模倣しないこと
・拡張機能またはアプリを機能が不十分な状態でリリースし、フル機能を使わせるためにユーザーに広告のクリックや個人情報入力を強制させることは禁止
と決められています。

2) 有料拡張で、マネタイズ

free trial がある。でもこんだけほとんど無料(のイメージが強い)だと、なかなか有料だとはやりにくい気もする。例外があったら教えてください。

f:id:serendipity4u:20170618125225p:plain

参考

qiita.com

qiita.com

liginc.co.jp

risaiku.net