ラベル JavaScript の投稿を表示しています。 すべての投稿を表示
ラベル JavaScript の投稿を表示しています。 すべての投稿を表示

2021年12月30日木曜日

-bash: yarn: command not found

Nodeはバージョンアップされるのが早いので、以前に投稿した記事の手順で、ちょくちょく安定版のバージョンに設定している。

NodebrewでNode.jsを最新版への切替方法

そして、今回、Nodeを最新バージョンにして、yarnを実行したら、エラーになった。

$ yarn -v
-bash: yarn: command not found

なので、yarnをinstallし直す。

$ npm install --global yarn

yarnのinstall後の確認。これで解決。

$ yarn -v
1.22.17

2021年3月10日水曜日

BootstrapVueを動かす

NuxtでBootstapVueを入れて、動かしてみた。

公式のサイトに情報はあるけど、前置きが長いのね。

冒頭にインストール方法とサンプルコードがあるのが個人的にはうれしいのだけどね。

https://bootstrap-vue.org/docs


ということで、後で再度同じことを行うときに、長い前置きを読まなくてよくするために備忘録を残しておく。

まず、BootstrapVueの設定。(yarnを使っている。BootstrapVueを追加する。)

yarn add bootstrap-vue

そんで、サンプルコード。

index.vueにコーディングする。(こちらのサイトの内容そのまま https://bootstrap-vue.org/docs/components/table)

これで、動きましたよ、と。

<template>
  <div>
    <b-table :items="items" hover="" striped=""></b-table>
  </div>
</template>


<script>
  export default {
    data() {
      return {
        items: [
          { age: 40, first_name: 'Dickerson', last_name: 'Macdonald' },
          { age: 21, first_name: 'Larsen', last_name: 'Shaw' },
          { age: 89, first_name: 'Geneva', last_name: 'Wilson' },
          { age: 38, first_name: 'Jami', last_name: 'Carney' }
        ]
      }
    }
  }
</script>

2021年2月21日日曜日

NodebrewでNode.jsを最新版への切替方法

プライベートでNuxtを使ったプログラミングしてて、Nuxtのバージョンを確認すると、Node.jsが古いので新しいものを使った方がいいよと、メッセージが表示された。

npx nuxt -v
 WARN You are using an unsupported version of Node.js (v10.20.1). It is recommended to use the latest LTS version (https://nodejs.org/en/about/releases)   10:03:02
 
 @nuxt/cli v2.15.1

まず、上記コマンド実行後のメッセージのサイトの内容を確認してみる。

https://nodejs.org/en/about/releases

Major Node.js versions enter Current release status for six months, which gives library authors time to add support for them. After six months, odd-numbered releases (9, 11, etc.) become unsupported, and even-numbered releases (10, 12, etc.) move to Active LTS status and are ready for general use. LTS release status is "long-term support", which typically guarantees that critical bugs will be fixed for a total of 30 months. Production applications should only use Active LTS or Maintenance LTS releases.

ActiveLTS 、 MaintenanceLTS のどちらかを使った方がいいみたいだ。

今は、自分の環境はv10で、最新のv10にすれば大丈夫だけど、後先短いのでv14に切り替えることにする。

そういえば、Node.jsは長い間、バージョン切り替えてなかった記憶なので、切替方法を探ってみる。

というか、過去に自分のブログで、同内容の記事を書いていたのを忘れてた。

まぁ、これは、Nodebrewのインストールの内容もあるのだけれども。

Nodeを再インストール(nodebrewにする)

ということで、この記事を参考にNode.jsのバージョンを切り替える。

現在のインストールされているNode.jsのバージョンを確認する。

nodebrew ls
 v10.10.0
 v10.20.1
 v14.1.0
 

既に、v14はあったのね。

でも、リビジョンが古いので、最新版を入手しよう。

nodebrew install stable
Fetching: https://nodejs.org/dist/v14.15.5/node-v14.15.5-darwin-x64.tar.gz
################################################################################################################################################################ 100.0%
Installed successfully

インストールできたので、v14に切り替える。

nodebrew use v14.15.5
use v14.15.5

v14に切り替わったか確認する。

node -v
v14.15.5
大丈夫みたいだ。

2019年10月14日月曜日

クライアントサイドだけで動かすReact.js

React.jsは、nodeがなくても動かすことができます。

React.jsのチュートリアルだと、nodeをインストールして動かすことになる。
なので、React.jsってnodeが前提なのか?と思ってしまう人もいるのではないでしょうか。

チュートリアル:React の導入

試しにhtml作って、Reactとbabelのjsは、CDNのリンク先から読み込むようにした。
ちゃんと動いた。

■ReactのHello World
 Hello World React のいちばん短い例はこのようになります:

■ReactのCDN
 CDN リンク
■babelのCDN
 babel-standalone

<!DOCTYPE html>
<html>
<head>
  <script crossorigin="" src="https://unpkg.com/react@16/umd/react.production.min.js"></script>
  <script crossorigin="" src="https://unpkg.com/react-dom@16/umd/react-dom.production.min.js"></script>
  <script crossorigin="" src="https://cdnjs.cloudflare.com/ajax/libs/babel-standalone/6.26.0/babel.min.js"></script>
</head>
<body>
  <div id="root">
</div>
<script type="text/babel">
    ReactDOM.render(
      <h1>Hello, world!</h1>,
      document.getElementById('root')
    )    
  </script>
</body>
</html>

2018年10月11日木曜日

Node express ect multerのサンプルをGitHubで公開

以前にNode express ect multerでファイルアップロードする機能を実装した記事を書いた。
今回は、そのNodeのプロジェクトを少しブラッシュアップして、GitHubに登録、公開した。
※ブラッシュアップ箇所は、日本語を英語に変更、プログラム内の不要なステートメントの削除など。

node express ect multerでファイルアップロード

手順は次のとおり。
自PCはMac book Pro、masOS High Sierra バージョン10.13.6

GitHubで新規リポジトリを作成する。
GitHubの自分のリポジトリの画面で、New repositoryボタンをクリック。


Repository nameに、multer_sample を入力。
Initialize this repository with a README をチェック。
Add .gitignoreで、Nodeを選択。
これら以外は、デフォルト値のまま。
Create repositoryボタンをクリック。



リポジトリが作成直後。
次の手順に進める。


自分のPCに作成したリポジトリをCloneするために、Clone or downloadボタンをクリック、SSHでClone用のテキストをコピーする。



自PCにmulter_sampleのプロジェクトをCloneする。
Gitのコマンドを入力する。その際にGitHubに登録したSSH keyのパスフレーズを聞かれるので入力が必要。
※[XXXXX]はユーザディレクトリ。

git clone git@github.com:takaharu-kobayashi/multer_sample.git
Cloning into 'multer_sample'...
Enter passphrase for key '/Users/[XXXXX]/.ssh/id_rsa': 
remote: Enumerating objects: 4, done.
remote: Counting objects: 100% (4/4), done.
remote: Compressing objects: 100% (3/3), done.
remote: Total 4 (delta 0), reused 0 (delta 0), pack-reused 0
Receiving objects: 100% (4/4), done.


自PCにmulter_sampleプロジェクトをClone直後。次の手順に進む。



multer_sampleにプログラム一式をコピーする。



multer_sampleプロジェクトの状態を確認してみる。
Gitのコマンドを入力する。

cd ./multer_sample/
git status
On branch master
Your branch is up to date with 'origin/master'.

Untracked files:
  (use "git add ..." to include in what will be committed)

 app.js
 bin/
 package.json
 public/
 routes/
 views/

nothing added to commit but untracked files present (use "git add" to track)


コピーしたプログラム一式をステージ領域に登録、確認をする。
Gitのコマンドを入力する。

git add .
git status
On branch master
Your branch is up to date with 'origin/master'.

Changes to be committed:
  (use "git reset HEAD ..." to unstage)

 new file:   app.js
 new file:   bin/www
 new file:   package.json
 new file:   public/javascripts/jquery-2.1.4.min.js
 new file:   public/uploads/dummy.txt
 new file:   routes/index.js
 new file:   views/error.ect
 new file:   views/footer.ect
 new file:   views/index.ect
 new file:   views/layout.ect
 new file:   views/script.ect


自PCのGitのリポジトリへ、前の操作でステージ領域に登録された内容をコミットする。
Gitのコマンドを入力する。

git commit -m "Added multer sample files"
[master f20cf5d] Added multer sample files
 11 files changed, 296 insertions(+)
 create mode 100644 app.js
 create mode 100755 bin/www
 create mode 100644 package.json
 create mode 100644 public/javascripts/jquery-2.1.4.min.js
 create mode 100644 public/uploads/dummy.txt
 create mode 100644 routes/index.js
 create mode 100644 views/error.ect
 create mode 100644 views/footer.ect
 create mode 100644 views/index.ect
 create mode 100644 views/layout.ect
 create mode 100644 views/script.ect


GitHubのリポジトリへ、自PCのGitリポジトリにコミットした内容をPushする。
Gitのコマンドを入力する。その際にGitHubに登録したSSH keyのパスフレーズを聞かれるので入力が必要。
※[XXXXX]はユーザディレクトリ。

git push
Enter passphrase for key '/Users/[XXXXX]/.ssh/id_rsa': 
Counting objects: 19, done.
Delta compression using up to 4 threads.
Compressing objects: 100% (14/14), done.
Writing objects: 100% (19/19), 32.59 KiB | 5.43 MiB/s, done.
Total 19 (delta 0), reused 0 (delta 0)
To github.com:takaharu-kobayashi/multer_sample.git
   80e8133..f20cf5d  master -> master


GitHubの画面でPushされた内容を確認する。問題なくPushした内容が反映されているみたいだ。



次は念のため、GitHubのmulter_sampleプロジェクトをCloneして動作するか確認する。
自PCのmulter_sampleプロジェクトがあるディレクトリではない別のディレクトリでCloneを行う。
Gitのコマンドを入力する。その際にGitHubに登録したSSH keyのパスフレーズを聞かれるので入力が必要。
※[XXXXX]はユーザディレクトリ。

git clone git@github.com:takaharu-kobayashi/multer_sample.git
Cloning into 'multer_sample'...
Enter passphrase for key '/Users/[XXXXX]/.ssh/id_rsa': 
remote: Enumerating objects: 23, done.
remote: Counting objects: 100% (23/23), done.
remote: Compressing objects: 100% (17/17), done.
remote: Total 23 (delta 1), reused 19 (delta 0), pack-reused 0
Receiving objects: 100% (23/23), 33.63 KiB | 242.00 KiB/s, done.
Resolving deltas: 100% (1/1), done.


multer_sampleプロジェクトに必要なパッケージをインストールする。
npmのコマンドを入力する。
※package.json内で指定しているバージョンがdeprecateになっているものがある。2016年1月に作成したプログラムなので古いから、deprecateになっててもおかしくない。動作確認が目的なので、とりあえずそのままにしておく。

cd ./multer_sample/
npm install
npm WARN deprecated jade@1.11.0: Jade has been renamed to pug, please install the latest version of pug instead of jade
npm WARN deprecated constantinople@3.0.2: Please update to at least constantinople 3.1.1
npm WARN deprecated transformers@2.1.0: Deprecated, use jstransformer
npm WARN deprecated coffee-script@1.12.7: CoffeeScript on NPM has moved to "coffeescript" (no hyphen)
npm notice created a lockfile as package-lock.json. You should commit this file.
added 136 packages from 155 contributors and audited 212 packages in 3.884s
found 15 vulnerabilities (8 low, 2 moderate, 5 high)
  run `npm audit fix` to fix them, or `npm audit` for details


いよいよ、multer_sampleプロジェクトを動作させる。
npmのコマンドを入力する。

npm start


ブラウザで、multer_sampleプロジェクトを表示してみる。
ちゃんと表示された。あとアップロードも正常に動いた。
これで終わり。


ちなみに、GitHub上のmulter_sampleのリンクは次のとおり。

https://github.com/takaharu-kobayashi/multer_sample






2016年5月24日火曜日

javascript Dateで前月と翌月の設定について

javascriptで日時を扱う時は、次のようにDateオブジェクトを生成して使用する。

var date = new Date();

そして、Dateオブジェクトには月を設定する関数(setMonth)がある。
次のように使用する。

date.setMonth(month);

なので、Dateオブジェクトの前月、翌月はsetMonthを設定することで可能だ。
前月の場合はこんな感じ。

date.setMonth(date.getMonth() - 1);


翌月の場合はこんな感じ。

date.setMonth(date.getMonth() + 1);


で、前月と翌月の設定はできそうであるが、はまったことがある。
当日が31日で、当日の前月と当日の翌月が30日までしかない場合に
当日(31日)の前月と当日が、setMonthだとうまく設定できなかったのだ。
次のコードのような場合だ。

function dateTest1() {
    var date = new Date();
    date.setMonth(5);//6月
    date.setDate(0);//5月の最終日を設定

    console.log("date.getMonth() = " + date.getMonth());
    console.log("date.getDate() = " + date.getDate());

    var previousM = new Date(date.getTime());
    previousM.setMonth(previousM.getMonth() - 1);

    console.log("previousM.getMonth() = " + previousM.getMonth());
    console.log("previousM.getDate() = " + previousM.getDate());

    var nextM = new Date(date.getTime());
    nextM.setMonth(nextM.getMonth() + 1);

    console.log("nextM.getMonth() = " + nextM.getMonth());
    console.log("nextM.getDate() = " + nextM.getDate());
}


このコードの実行結果は次のようになった。

date.getMonth() = 4
date.getDate() = 31
previousM.getMonth() = 4
previousM.getDate() = 1
nextM.getMonth() = 6
nextM.getDate() = 1


前月に設定したはずが当月と同じ。それで翌月に設定していたはずが翌々月になっている。
今回の場合、当日は5月31日である。それで当日のDateオブジェクトにたいしてsetMonthに当月の-1した値を設定すれば4月になるのではと思うのだが、4月31日なんてものはない。4月は30日までだ。なので、javascriptが5月1日にしている。(previousMのgetMonth()とgetDate()の結果)
なお、前月はsetMonthに当月の+1した値を設定すれば6月になるのではと思うのだが、6月31日なんてものはない。6月は30日までだ。なので、javascriptが7月1日にしている。(nextMのgetMonth()とgetDate()の結果)
それで、この問題をどう解消しようかと考えて次のコードで対応することにした。
どうしたかというと、setMonthを使用せずに、setDateを使用して、前月と翌月を設定させることにした。
setDate(0)は前月の最終日がされるので、当月のDateオブジェクトに対して、setDate(0)を行い前月を設定する。
そして、当月の最終日が設定されているDateオブジェクトに対して、setDate(date.getDate() + 1)をすることで、翌月を設定するようにしている。

function dateTest2() {
    var date = new Date();
    date.setMonth(5);//6月
    date.setDate(0);//5月の最終日を設定

    console.log("date.getMonth() = " + date.getMonth());
    console.log("date.getDate() = " + date.getDate());

    var previousM = new Date(date.getTime());
    previousM.setDate(0);

    console.log("previousM.getMonth() = " + previousM.getMonth());
    console.log("previousM.getDate() = " + previousM.getDate());

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

    console.log("nextM.getMonth() = " + nextM.getMonth());
    console.log("nextM.getDate() = " + nextM.getDate());
}


コードの実行結果は次のようになった。
ちゃんと、前月と翌月が設定できていた。

date.getMonth() = 4
date.getDate() = 31
previousM.getMonth() = 3
previousM.getDate() = 30
nextM.getMonth() = 5
nextM.getDate() = 1

2016年2月29日月曜日

node express ectにbootstrapを組み入れてみる

node express ectにbootstrapを組み入れてみる。

まず、次のサイトにアクセスする。

http://getbootstrap.com/


"Download Bootstrap"ボタンを押す。


"Download Bootstra"ボタンを押すとzipファイル(自分がダウンロード時のファイル名は、"bootstrap-3.3.6-dist.zip"でした。) をダウンロードする。

そして、ダウンロードしたzipファイルを解凍する。


この解凍されたcss、fonts、jsのフォルダをnodeのプロジェクトのpublicフォルダにコピーする。
nodeのプロジェクトのpublicフォルダには、はじめからjs及びcss用のフォルダとして、それぞれjavascripts、stylesheetsフォルダがあるが、今回はbootstrapのために、これらのフォルダは使用せず、ダウンロードしたzipファイルから解凍されたcss、fonts、jsのフォルダをそのまま、コピーすることにする。


コピー後


そして、今回は組み込んだbootstrapの動作確認のために、bootstrapのExsamplesにあるBootstrap themeのButtonsの部分を取り込んで正しく表示できるようにする。
* Examplesの中身を確認する方法は以下の記事を参照のこと。
  Bootstrapのサンプルを見る

Bootstrap themeのButtons部分のコードは次の通り。
これをindex.ectファイル内に組み込む。

<div class="page-header">
<h1>Buttons</h1>
</div>
<button class="btn btn-lg btn-default" type="button">Default</button>
<button class="btn btn-lg btn-primary" type="button">Primary</button>
<button class="btn btn-lg btn-success" type="button">Success</button>
<button class="btn btn-lg btn-info" type="button">Info</button>
<button class="btn btn-lg btn-warning" type="button">Warning</button>
<button class="btn btn-lg btn-danger" type="button">Danger</button>
<button class="btn btn-lg btn-link" type="button">Link</button>
   
<button class="btn btn-default" type="button">Default</button>
<button class="btn btn-primary" type="button">Primary</button>
<button class="btn btn-success" type="button">Success</button>
<button class="btn btn-info" type="button">Info</button>
<button class="btn btn-warning" type="button">Warning</button>
<button class="btn btn-danger" type="button">Danger</button>
<button class="btn btn-link" type="button">Link</button>

<button class="btn btn-sm btn-default" type="button">Default</button>
<button class="btn btn-sm btn-primary" type="button">Primary</button>
<button class="btn btn-sm btn-success" type="button">Success</button>
<button class="btn btn-sm btn-info" type="button">Info</button>
<button class="btn btn-sm btn-warning" type="button">Warning</button>
<button class="btn btn-sm btn-danger" type="button">Danger</button>
<button class="btn btn-sm btn-link" type="button">Link</button>

<button class="btn btn-xs btn-default" type="button">Default</button>
<button class="btn btn-xs btn-primary" type="button">Primary</button>
<button class="btn btn-xs btn-success" type="button">Success</button>
<button class="btn btn-xs btn-info" type="button">Info</button>
<button class="btn btn-xs btn-warning" type="button">Warning</button>
<button class="btn btn-xs btn-danger" type="button">Danger</button>
<button class="btn btn-xs btn-link" type="button">Link</button>


いよいよ、動作確認。
ブラウザで表示すると次のようになった。組み込んだbootstrapが、正しく動いている。



今回のbootstrapの動作確認に関連あるソースコードは以下の通り。

=== app.js ===
変更部分はexpressコマンドでプロジェクト生成後にect用に変更した13〜18行目

var express = require('express');
var path = require('path');
var favicon = require('serve-favicon');
var logger = require('morgan');
var cookieParser = require('cookie-parser');
var bodyParser = require('body-parser');

var routes = require('./routes/index');
var users = require('./routes/users');

var app = express();

// ECT view engine setup
var ECT = require('ect');
var ectRenderer = ECT({ watch: true, root: __dirname + '/views', ext: '.ect'});
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'ect');
app.engine('ect', ectRenderer.render);

// uncomment after placing your favicon in /public
//app.use(favicon(path.join(__dirname, 'public', 'favicon.ico')));
app.use(logger('dev'));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
app.use(cookieParser());
app.use(express.static(path.join(__dirname, 'public')));

app.use('/', routes);
app.use('/users', users);

// catch 404 and forward to error handler
app.use(function(req, res, next) {
    var err = new Error('Not Found');
    err.status = 404;
    next(err);
});

// error handlers

// development error handler
// will print stacktrace
if (app.get('env') === 'development') {
    app.use(function(err, req, res, next) {
        res.status(err.status || 500);
        res.render('error', {
            message: err.message,
            error: err
        });
    });
}

// production error handler
// no stacktraces leaked to user
app.use(function(err, req, res, next) {
    res.status(err.status || 500);
    res.render('error', {
        message: err.message,
        error: {}
    });
});

module.exports = app;


=== index.js ===
変更部分はなし。expressコマンドでプロジェクト生成後のそのまま。ただ載せているだけ。

var express = require('express');
var router = express.Router();

/* GET home page. */
router.get('/', function(req, res, next) {
    res.render('index', { title: 'Express' });
});

module.exports = router;


=== error.ect ===
ectのエラー出力のためのテンプレート。bootstrapとは関係ない。ただ載せているだけ。

<html>
<head>
    <title>Error <%= @error.status %>>/title>
</head>
<body>
<span>
    Error Status: <%= @error.status %>
    <hr />
    <pre><%= @error.stack %></pre>
</span>
</body>
</html>


=== footer.ect ===
ectのフッター部分のテンプレート。bootstrapとは関係ない。ただ載せているだけ。

<div id="footer">
<div class="left">
Generated by ECT</div>
<% content 'footer-info' %>
</div>


=== index.ect ===
また、ExapmlesのButtons部分を取り込んでいる。8〜46行目

<% extend 'layout' %>

<%= "This is sample"  %>

<h1>
<%= @title %></h1>
Welcome to <%= @title %>



<div class="page-header">
<h1>
Buttons</h1>
</div>
<button class="btn btn-lg btn-default" type="button">Default</button>
<button class="btn btn-lg btn-primary" type="button">Primary</button>
<button class="btn btn-lg btn-success" type="button">Success</button>
<button class="btn btn-lg btn-info" type="button">Info</button>
<button class="btn btn-lg btn-warning" type="button">Warning</button>
<button class="btn btn-lg btn-danger" type="button">Danger</button>
<button class="btn btn-lg btn-link" type="button">Link</button>

<button class="btn btn-default" type="button">Default</button>
<button class="btn btn-primary" type="button">Primary</button>
<button class="btn btn-success" type="button">Success</button>
<button class="btn btn-info" type="button">Info</button>
<button class="btn btn-warning" type="button">Warning</button>
<button class="btn btn-danger" type="button">Danger</button>
<button class="btn btn-link" type="button">Link</button>

<button class="btn btn-sm btn-default" type="button">Default</button>
<button class="btn btn-sm btn-primary" type="button">Primary</button>
<button class="btn btn-sm btn-success" type="button">Success</button>
<button class="btn btn-sm btn-info" type="button">Info</button>
<button class="btn btn-sm btn-warning" type="button">Warning</button>
<button class="btn btn-sm btn-danger" type="button">Danger</button>
<button class="btn btn-sm btn-link" type="button">Link</button>

<button class="btn btn-xs btn-default" type="button">Default</button>
<button class="btn btn-xs btn-primary" type="button">Primary</button>
<button class="btn btn-xs btn-success" type="button">Success</button>
<button class="btn btn-xs btn-info" type="button">Info</button>
<button class="btn btn-xs btn-warning" type="button">Warning</button>
<button class="btn btn-xs btn-danger" type="button">Danger</button>
<button class="btn btn-xs btn-link" type="button">Link</button>

<% block 'footer-info' : %>
  <div class="right">
page: sample</div>
<% end %>


=== layout.ect ===
ectのレイアウト外枠。
以下のbootstrapのテンプレート部分(http://getbootstrap.com/getting-started/#download に載っている。)を取り込んでいる。5、6、8〜10行目


<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <title><%- @title %></title>
        <link href="css/bootstrap.min.css" rel="stylesheet">
        <% include 'script' %>
        <script src="js/bootstrap.min.js"></script>
    </head>
    <body>
        <% content %>
        <% include 'footer' %>
    </body>
</html>


=== script.ect ===
ectのscriptタグ部分箇所。bootstrapを動作させるために必要なjqueryの読み込みを定義。また、bootstrapsのjsの定義より前の行に定義する必要あり。

<script src="./javascripts/jquery-2.1.4.min.js"></script>


=== package.json ===
bootstrapとは関係ない。ただ載せているだけ。

{
    "name": "bootstrap",
    "version": "0.0.0",
    "private": true,
    "scripts": {
        "start": "node ./bin/www"
    },
    "dependencies": {
        "body-parser": "~1.13.2",
        "cookie-parser": "~1.3.5",
        "debug": "~2.2.0",
        "express": "~4.13.1",
        "jade": "~1.11.0",
        "morgan": "~1.6.1",
        "serve-favicon": "~2.3.0"
    }
}

2016年2月23日火曜日

node express POSTのデータの送信と受信

node express ectでクライアントからサーバにPOSTでデータの送信と受信する処理をプログラミングしてみました。formのsubmitからの送信の場合とjQueryを使用して送信した場合です。

node expressのプロジェクトを生成して自分自身がプログラミングしたソースは次の通りです。(※実際はindex.ect以外のectファイルの編集もしていますが、今回の記事の内容と関係ないので割愛します。)

=== app.js ===
今回、クライアントから受信するPOSTデータをサーバ側で処理するプログラム(sendreceive.js)を紐つけています。(9、29行目)
var express = require('express');
var path = require('path');
var favicon = require('serve-favicon');
var logger = require('morgan');
var cookieParser = require('cookie-parser');
var bodyParser = require('body-parser');

var routes = require('./routes/index');
var sendreceive = require('./routes/sendreceive');

var app = express();

// ECT view engine setup
var ECT = require('ect');
var ectRenderer = ECT({ watch: true, root: __dirname + '/views', ext: '.ect'});
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'ect');
app.engine('ect', ectRenderer.render);

// uncomment after placing your favicon in /public
//app.use(favicon(path.join(__dirname, 'public', 'favicon.ico')));
app.use(logger('dev'));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
app.use(cookieParser());
app.use(express.static(path.join(__dirname, 'public')));

app.use('/', routes);
app.use('/sendreceive', sendreceive);

// catch 404 and forward to error handler
app.use(function(req, res, next) {
    var err = new Error('Not Found');
    err.status = 404;
    next(err);
});

// error handlers

// development error handler
// will print stacktrace
if (app.get('env') === 'development') {
    app.use(function(err, req, res, next) {
        res.status(err.status || 500);
        res.render('error', {
            message: err.message,
            error: err
        });
    });
}

// production error handler
// no stacktraces leaked to user
app.use(function(err, req, res, next) {
    res.status(err.status || 500);
    res.render('error', {
        message: err.message,
        error: {}
    });
});


module.exports = app;

=== sendreceive.js ===
クライアントから受信したデータ"sendParam"を、クライアントにJSONのデータに含めて、送信しています。(6行目)
var express = require('express');
var router = express.Router();

/* POST ajax listing. */
router.post('/', function(req, res, next) {
    res.send({"send parameter is" : req.body.sendParam});
});

module.exports = router;

=== index.ect ===
formのsubmitして送信する場合は、"from form" を送信するようにしています。 (14行目)
jQueryを使用して送信する場合は、"from ajax" を送信するようにしています。 (36行目)
<% extend 'layout' %>

<%= "This is sample"  %>


<div id="drag-area" style="background-color: lightgrey; text-align: center;">
ajaxボタン送信ボタンを押すと、ajax送信します。<br />
<div class="btn-group">
<button id="btn">ajax送信</button>
</div>
</div>
<form action="/sendreceive" method="post" name="frm">
<input name="sendParam" type="hidden" value="from form" />
    >input type="submit" value="form送信" />
</form>
<div id="test">
</div>
<% block 'footer-info' : %>
  <div class="right">
page: sample</div>
<script>

$(function(){
    $('#btn').click(function() {
        sendData();
    });
});

function sendData() {

    $.ajax({
        url: "http://" + location.host + "/sendreceive",
        type: "post",
        data: {"sendParam": "from ajax"},
        success: function(data) {
            alert("データが送信されました。 : " + JSON.stringify(data));
        }
    });
}

</script>
<% end %>

また、後でメモとして見返すことを考えて、package.jsonも載せておきます。

=== package.json
{
    "name": "xxx",
    "version": "0.0.0",
    "private": true,
    "scripts": {
        "start": "node ./bin/www"
    },
    "dependencies": {
        "body-parser": "~1.13.2",
        "cookie-parser": "~1.3.5",
        "debug": "~2.2.0",
        "express": "~4.13.1",
        "jade": "~1.11.0",
        "morgan": "~1.6.1",
        "serve-favicon": "~2.3.0",
        "node-stringify": "0.0.19"
    }
}

動作確認したスクリーンショットは次の通りです。

*初期画面表示時
 jQueryを使用しての確認は"ajax送信"ボタンを押下して確認します。
 formのsubmitからの確認は"form送信"ボタンを押下して確認します。





*"ajax送信"ボタンを押下後




*"form送信"ボタンを押下後


2016年2月8日月曜日

node Readable readメソッドの戻り値のバッファについて

nodeのReadableオブジェクトのreadメソッドですが、
readメソッドの引数には、readメソッド実行結果のバッファのバイト数を設定することができるのですが、このバッファの値は、どのように設定されるのか確認してみました。

さて、確認方法ですが、以前にnodeのファイルアップロード処理の記事を書きましたが、
そのファイルアップロードされた内容をReadableオブジェクトのreadメソッドで取得してみました。

ファイル内容は次の通りです。
=== test.txt ===

abcあ


そして、app.jsで今回、確認でコーディングした部分です。(app.js全体でなく、該当部分のみです。)
=== app.js ===

var fs = require('fs');

app.post('/up', upload.single('upFile'), function (req, res, next) {
    var readableStream = fs.createReadStream(req.file['path']);
    readableStream.on('readable', function() {
        var chunk;
        while (null !== (chunk = readableStream.read(8))) {
            console.log('chunk[' + chunk + ']');
            for (var i = 0; i < chunk.length; i++) {
                console.log("chunk[" + i + "] = " + chunk[i] + " : chunk[" + i + "].toString(16) = " + chunk[i].toString(16));
            }

        }
    });
    res.render('index');
});


実行結果は、次の通りです。

chunk[abcあ
]
chunk[0] = 97 : chunk[0].toString(16) = 61
chunk[1] = 98 : chunk[1].toString(16) = 62
chunk[2] = 99 : chunk[2].toString(16) = 63
chunk[3] = 227 : chunk[3].toString(16) = e3
chunk[4] = 129 : chunk[4].toString(16) = 81
chunk[5] = 130 : chunk[5].toString(16) = 82
chunk[6] = 10 : chunk[6].toString(16) = a

readメソッドの実行結果のバッファそのものは、ファイル内容の文字列そのものです。
そして、そのバッファを1つずつ、取り出した内容ですが
"a"の文字は、97になっています。これは、UTF8のaを10進数にしているから、97なのです。なので、16進数だと、61ですね。
ちなみに、"あ"の文字の場合は、3バイトなので、16進数だと、e3,81,82になります。
この場合、繰り返しますが、1文字3バイトです。
なので、バッファリング後に文字列処理がある場合を考慮して
バッファリングする時に、文字コードを判定して、1文字に何バイトかの判断が必要になります。
例えば、"あ"の文字の場合に、e3,81のみで、82を次の文字と判断したらいけないです。
e3,81,82です。

2016年1月11日月曜日

node express ect multerでファイルアップロード

node express ect multerでファイルアップロード処理を作成してみました。
ちなみに、ファイルアップロードは、HTML5のFile APIを使用して、PCからブラウザにファイルをドラッグアンドドロップで、実行するようにしました。
次のサイトを参考にしました。

https://github.com/expressjs/multer

http://soraxism.com/soraxism/blog/html5%E3%81%AEfile-api%E3%82%92%E4%BD%BF%E7%94%A8%E3%81%97%E3%81%A6%E3%80%81%E3%83%89%E3%83%A9%E3%83%83%E3%82%B0%EF%BC%86%E3%83%89%E3%83%AD%E3%83%83%E3%83%97%E3%81%A7%E3%83%95%E3%82%A1%E3%82%A4

プログラムソースは次の通りです。

=== app.js ===
メインプログラムですね。
"/"のパスの処理が呼ばれたら、ファイルアップロード入力フォームを表示します。
(開発環境だと、http://localhost:3000/ に該当します。)

"/up"のパスの処理が呼ばれたら、ファイルアップロード処理を行っています。
(開発環境だと、http://localhost:3000/up に該当します。)
そして、アップロードされたファイルの属性をコンソールに出力させてます。

var multer = require('multer');

var express = require('express');
var path = require('path');
var favicon = require('serve-favicon');
var logger = require('morgan');
var cookieParser = require('cookie-parser');
var bodyParser = require('body-parser');

var app = express();

var upload = multer({
    dest: __dirname + '/public/uploads/'
});

// ECT view engine setup
var ECT = require('ect');
var ectRenderer = ECT({ watch: true, root: __dirname + '/views', ext: '.ect'});
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'ect');
app.engine('ect', ectRenderer.render);

// routes setup
var routes = require('./routes/index');

app.use('/', routes);

app.post('/up', upload.single('upFile'), function (req, res, next) {
    for (var item in req.file) {
        console.log(item + ":" + req.file[item]);
    }
   res.render('index');
});

// uncomment after placing your favicon in /public
//app.use(favicon(path.join(__dirname, 'public', 'favicon.ico')));
app.use(logger('dev'));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
app.use(cookieParser());
app.use(express.static(path.join(__dirname, 'public')));

// catch 404 and forward to error handler
app.use(function(req, res, next) {
    var err = new Error('Not Found');
    err.status = 404;
    next(err);
});

// error handlers

// development error handler
// will print stacktrace
if (app.get('env') === 'development') {
    app.use(function(err, req, res, next) {
        res.status(err.status || 500);
        res.render('error', {
            message: err.message,
           error: err
        });
    });
}

// production error handler
// no stacktraces leaked to user
app.use(function(err, req, res, next) {
    res.status(err.status || 500);
    res.render('error', {
        message: err.message,
        error: {}
    });
});

module.exports = app;


=== index.js ===
ファイルアップロード入力フォーム(index.ect)表示を促しています。
ただ、それだけです。

var express = require('express');
var router = express.Router();

/* GET home page. */
router.get('/', function(req, res, next) {
    res.render('index');
});

module.exports = router;


=== index.ect ===
ファイルアップロードの入力フォームです。

<% extend 'layout' %>

<div id="drag-area" style="background-color: lightgrey; text-align: center;">
アップロードするファイルをドロップ<br />
または<br />
    <div class="btn-group">
        <input name="upFile" style="display: none;" type="file" />
            <button id="btn">ファイルを選択</button>
    </div>
</div>
<% block 'footer-info' : %>
<div class="right">
page: upload</div>
<script>

$(function(){
    $('#drag-area').bind('drop', function(e){
        e.preventDefault();
        var files = e.originalEvent.dataTransfer.files;
        upload(files);
    }).bind('dragenter', function(){
        return false;
    }).bind('dragover', function(){
        return false;
    });

    $('#btn').click(function() {
        $('input[type="file"]').click();
    });
 
    $('input[type="file"]').change(function(){
        var files = this.files;
        upload(files);
    });
});

function upload(files) {

    if (files == null || files.length == 0) {
        return;  
    }

    var frm = new FormData();
    frm.append("upFile", files[0]);

    $.ajax({
        url: 'http://' + location.host + '/up',
        type: 'post',
        data: frm,
        processData: false,
        contentType: false,
        success: function(data) {
            alert('ファイルがアップロードされました。');
        }
    });
}

</script>
<% end %>

package.json

{
    "name": "upload",
    "version": "0.0.0",
    "private": true,
    "scripts": {
        "start": "node ./bin/www"
    },
    "dependencies": {
        "body-parser": "~1.13.2",
        "cookie-parser": "~1.3.5",
        "debug": "~2.2.0",
        "express": "~4.13.1",
        "jade": "~1.11.0",
        "morgan": "~1.6.1",
        "serve-favicon": "~2.3.0",
        "ect": "~0.5.9"
    }
}

なお、今回multerを使用していてハマったのが
上記のように、multerを変数に格納するのでなく、次のようにapp.useを使用するサンプルがググると見つかります。

app.use(multer({ dest: './upload/'}));

この通りに、コーディングして、動作させると次のエラーが発生しました。


TypeError: app.use() requires middleware functions

このエラーメッセーじをググると、stackoverflowに次の記事が見つかりました。
app.use…は使用できないみたいです。
そもそも、上記のmulterのgithubの使用方法に、app.use…は記載されてないですね。


2016年1月4日月曜日

node expressで外部jsファイルを使用する(scriptタグから)

node expressでjqueryを使用する必要があったので
htmlのscriptタグのsrc属性にjqueryのパスの設定して、使用できるようにしました。

expressのプロジェクトのディレクトリは、次のようになっており
~/project_name/javascripts/ に jquery-2.1.4.min.js を配置しました。

project_name
├ bin
├ node_modules
├ public
│ ├ images
│ ├ javascripts
│ │ └ jquery-2.1.4.min.js
│ └ stylesheets
├ routes
└ views

そして、htmlのscriptタグは次のように、定義しました。

<script src="./javascripts/jquery-2.1.4.min.js"></script>


これで、jqueryが使用できました。
まぁ、javascript用のディレクトリが用意されているので、そこにjsファイルを
配置して、それをそのまま使用しただけです。

2016年1月3日日曜日

node expressのURLのハンドリング

nodeのexpressでURLのpathnameによって、動作させるプログラムを紐つける方法についてのメモです。
(*URLは開発環境での場合です。)

次のURL2つをそれぞれ、別のプログラムを動作させます。

1)http://localhost:3000/
2)http://localhost:3000/test

app.jsのapp.use関数の第1引数にpathnameを設定します。
そして、第2引数は、動作させるプログラムを設定します。

1)の場合は、app.use('/', routes);
2)の場合は、app.use('/test', test);

動作させるプログラムの、router.getの第1引数は'/'を設定します。
2)の場合も、'/'を設定します。'/test'を設定してはダメです。
'/test'を設定して、動作させるとHTTPステータス404(Not Found)になります。

2)を動作させるために、関連する箇所のプログラムは以下になります。

app.jsの先頭部分

var express = require('express');
var path = require('path');
var favicon = require('serve-favicon');
var logger = require('morgan');
var cookieParser = require('cookie-parser');
var bodyParser = require('body-parser');

var app = express();

// ECT view engine setup
var ECT = require('ect');
var ectRenderer = ECT({ watch: true, root: __dirname + '/views', ext: '.ect'});
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'ect');
app.engine('ect', ectRenderer.render);

// routes setup
var routes = require('./routes/index');
var test = require('./routes/test');

app.use('/', routes);
app.use('/test', test);


test.jsの内容

var express = require('express');
var router = express.Router();

/* GET home page. */
router.get('/', function(req, res, next) {
    res.render('test');
});

module.exports = router;


2016年1月1日金曜日

Error: Cannot find module 'express'

nodeで、ectを使用したプログラミングをしてみようと思い
ググって、次のサイトの記事を参考にさせてもらい
Webアプリを作成しようとしたのですが、



Error: Cannot find module 'express' というエラーが出て、
Webアプリが起動しない、このエラーをググると
次のサイトが見つかりました。


このサイトに記載されているように、次のコマンドを実行して、
問題を解決しようとしました。

sudo npm link express

ですが、似たようなエラーが複数出たのです。
発生したエラーは、次の通りです。

Error: Cannot find module 'serve-favicon'

Error: Cannot find module 'morgan'

Error: Cannot find module 'cookie-parser'

Error: Cannot find module 'body-parser'


Error: Cannot find module 'express' と同じような、エラーだったので、
sudo npm link express と同じように、次のコマンドを順番に実行することで
これらのエラーは発生しなくなりました。


sudo npm link serve-favicon

sudo npm link morgan

sudo npm link cookie-parser

sudo npm link body-parser



今回、発生したエラーは、app.jsというプログラムの先頭が次のようになっており
必要なモジュールを取り込んでないため、発生したエラーのようでした。
本当は、今回のエラーを回避したコマンドの実行でなく、
事前の環境設定の方法に誤りがあるような気がします。
ですので、本件については、時間を作って、調べてみようかと思います。

var express = require('express');
var path = require('path');
var favicon = require('serve-favicon');
var logger = require('morgan');
var cookieParser = require('cookie-parser');
var bodyParser = require('body-parser');


2015年10月4日日曜日

Herokuでexpressのwebアプリケーションを動かす。

expressアプリ作成及び動作確認の記事に続いて、今度はexpressのwebアプリケーションをHeroku上で動作させた時のメモです。
Herokuへwebアプリケーションを設置する方法は、HerokuのNode環境作成のメモの記事とほとんど同じ内容です。
が、全く同じ方法だと、expressのwebアプリケーションは正常に動作しませんでした。
その時の、解決方法もメモしておきます。

まず、Webアプリケーションのディレクトリに移動して、次のコマンドを入力します。
※expressアプリ作成及び動作確認の記事で作成した[xxxxx]ディレクトリに移動します。

    heroku create --stack cedar

そしたら、webアプリケーションサイトのURLとGitのURLが表示されるので、メモしておく。(メモしておいたほうがいいでしょう。)

次のコマンドを順番に入力して、Gitへの登録とwebアプリケーションのデプロイをします。
※[yyyyy]は任意のコメント。[zzzzz]は、前の操作で、表示されるWebアプリケーションサイトのURLの"https://" と ".herokuapp.com/" の間の文字列)

git init
git add .
git commit -m "[yyyyy]"
heroku git:remote -a [zzzzz]
git push heroku master

そして、webアプリケーションサイトのURLにアクセスすると、作成したWebアプリケーションが表示される。はずですが、次のエラー画面が表示されてしまいました。

どのエラーになっているのかを確認するために、ターミナルで次のコマンドを
入力して、ログを確認します。


heroku logs -t

すると、次のようなエラーログが出力されていました。

2015-09-27T00:40:38.142003+00:00 heroku[router]: at=error code=H10 desc="App crashed" method=GET path="/" host=[zzzzz].herokuapp.com request_id=a4dc2cec-8bdd-4be5-b1fe-0caaf311de15 fwd="223.133.135.59" dyno= connect= service= status=503 bytes=
2015-09-27T00:40:39.245105+00:00 heroku[router]: at=error code=H10 desc="App crashed" method=GET path="/favicon.ico" host=[zzzzz].herokuapp.com request_id=4ec20557-a3a4-4e84-8fd6-db35ad8ee197 fwd="223.133.135.59" dyno= connect= service= status=503 bytes=

そして、at=error code=H10 desc="App crashed" をググっても
何が原因で、エラーになっているかがわかりませんでした。

ローカルのMac上で正常に動作するのに、Heroku上ではエラーになるんだろうと考えます。
そして、Heroku上でエラーになるのは、やはり環境の設定に誤りがあるはずだ。と思いました。

しばらく、今までの環境作成の手順や作成したexpressのwebアプリケーションのプログラムソースなどを、見てみます。
すると、package.jsonに次のような記述があるのです。

  "scripts": {
    "start": "node ./bin/www"
  },

ということは、ローカルのMac上では、./bin/wwwのプログラムがまず
動作しているのでは?と。であるならば、Procfileの内容が間違っているはずだ。と
思い、Procfileの内容を確認します。
Procfileの内容は、次のようになっています。

web: node app.js

これは、app.jsでなく、./bin/wwwにすれば、Heroku上で、expressのwebアプリケーションが動くかもしれない。と思い、Procfileを次のように、書き換えます。

web: node ./bin/www

そして、ターミナルで、次のコマンドを順番に実行して、expressのwebアプリケーションをデプロイします。

git add .
git commit -m "[yyyyy]"
git push heroku master

そして、WebアプリケーションサイトのURLにアクセスすると、Mac上でexpressのwebアプリケーションを動作させた時と同じ画面が表示されました。








2015年10月3日土曜日

expressアプリ作成及び動作確認

expressのインストールメモの記事の続きですが、Macにexpressをインストール後に
expressのサンプルアプリを作成時のメモです。

アプリを設置するディレクトリに移動して、次のコマンドを実行します。
※[xxxxx]はアプリ名及びアプリ格納ディレクトリです。そして、[xxxxx]ディレクトリは存在してない状態です。事前に[xxxxx]ディレクトリは作成しないでください。

express [xxxxx]

すると、ターミナルにコマンド実行時のメッセージが出力されるのですが
最後の方に次のメッセージが表示されます。

   install dependencies:
     $ cd [xxxxx] && npm install

   run the app:
     $ DEBUG=[xxxxx]:* npm start

なので、指示通りに、次のコマンドを実行します。

cd [xxxxx] && npm install

すると、ターミナルでコマンド実行時のメッセージが出力されます。
その後に、上記の指示どおりに、次のコマンドでアプリを実行します。

DEBUG=[xxxxx]:* npm start

※ ググると node [xxxxx] のコマンドを実行する記事が見つかると思いますが、express 4.13.1 では正しく動作しません。node [xxxxx] のコマンドを実行すると、ターミナルに次のようなメッセージが表示されて、アプリは起動しません。

module.js:333
    throw err;
          ^

すると、ターミナルに次のメッセージが表示されて
ターミナルでの入力できない状態になります。
※controlキー + c で次の状態を終了できます。そして、expressも終了します。

  [xxxxx]:server Listening on port 3000 +0ms

そして、ブラウザ起動して、アドレスバーに次のURLを入力します。

http://localhost:3000/

すると、ブラウザの表示が次のようになっており、expressが動作しています。







2015年6月22日月曜日

javascriptの連想配列の配列

javascriptの連想配列は、ググると色んな記事が見当たるのですが、
連想配列の配列で、使用するのは、少ないように思います。

javascriptの場合は、連想配列の配列を使用するのだったら
2次元配列を使用するほうがよいのでしょうか?
(連想配列の配列の代替として、2次元配列が思い浮かんだのですが、
 他に良い方法とかあるのでしょうか?)

個人的には、連想配列は、キーと値が対になっているので、
キーの名前で、どの値が設定されているのかを推定できるので、
コードの可読性の観点で考えると、2次元配列よりは、連想配列の配列のほうが
よいと思うのですが。

ちなみに、私は、次のように、連想配列の配列を編集して使用しています。
var array = new Array();
array[array.length] = { "id": 1, "description": "description1" };
array[array.length] = { "id": 2, "description": "description2" };
array[array.length] = { "id": 3, "description": "description3" };