ERROR Cannot read property ‘toLowerCase’ of undefined

Posted by muchag | Nuxt.js |
初回投稿:2021-03-05 (金) 18:30:39 | 最終更新:2021-10-16 (土) 11:39:52

【環境】
create-nuxt-app: 3.5.2
Nuxt.js: 2.15.2
-> 2.15.4
Vue.js: 2.6.12
Node.js: 12.18.2
-> 14.16.1

このエラーは、エラー文は頼りにならないことが多いみたい。

色々なことが原因で、最終的にこういうエラーを吐くことになっているだけなので
毎度、原因を探る作業が必要になりそう。

原因を探るためには、コメントアウトを繰り返し
原因箇所を特定するところから始める。

私の場合は

において、掲題のエラーが出た。

Nginx の設定
気のせい?

以下の記事を書いたのは、Nuxt に触りたての頃。

今振り返ってみると、その後、Nuxt インストール時に
このような現象は起きていないので
気のせいだったかも?

ここまで

Nuxt2.15.2


yarn create nuxt-app hello

と普通にインストールしただけなのに
開発サーバを起動したら

ERROR Cannot read property ‘toLowerCase’ of undefined 11:19:35

at WebSocketServer.handleUpgrade (node_modules/ws/lib/websocket-server.js:193:27)
at WS.handleUpgrade (node_modules/@nuxt/content/lib/ws.js:21:21)
at WS.serve (node_modules/@nuxt/content/lib/ws.js:17:10)
at node_modules/@nuxt/content/lib/middleware.js:12:15
at call (node_modules/connect/index.js:239:7)
at next (node_modules/connect/index.js:183:5)
at next (node_modules/connect/index.js:161:14)
at next (node_modules/connect/index.js:161:14)
at WebpackBundler.middleware (node_modules/@nuxt/webpack/dist/webpack.js:2192:5)

というエラーが出た。

調査

泣きそうになりながら Google 先生へ質問してみた。

nuxt + エラーメッセージ

nuxt Cannot read property ‘toLowerCase’ of undefined

こちらで検索したところ
GitHub:Cannot read property toLowerCase of undefined(2019-07-24)
Qiita:Cannot read property ‘toLowerCase’ of undefinedのとき何を確認すべきか?(2020-12-09)
などが上位にでてきたんだけど
いずれもコーディングミスを原因とするもの。

  • HTML の記述ミス
  • SSR の問題?(よく理解できなかった)
  • javascript による undefine オブジェクトへの参照

どれも新規 Nuxt.js プロジェクトにはありえないので
検索ワードを変更してみることにした。

エラー発生ファイル名 + エラーメッセージ

上記エラーメッセージを引き起こしているファイル名を入れてみた。

WebpackBundler.middleware Cannot read property ‘toLowerCase’ of undefined

で検索すると、WebSocket に関わる記事が最初に出てきた。

中を見ると、エラーメッセージが全く同じ!

@nuxt/content

途中 @nuxt/content が原因っぽいことが書いてあったので
試しに、@nuxt/content を外してインストールしてみると
確かに件のエラーが出ない。

原因その1

更に読み進めると
GitHub:Nginx の WebSocket を有効にすると問題が解消される(2020-10-16)
との返信を見つけた。

解決その1

そこで
Qiita:NginxのリバースプロキシでWebソケットを通す際の設定(2019-12-28)
こちらを参考に、Nginx において WebSocket を有効に設定してみた。


server {
    listen       80;
    server_name  192.168.56.xxx;

+   proxy_http_version 1.1;
+   proxy_set_header Upgrade $http_upgrade;
+   proxy_set_header Connection "upgrade";

    location / {
        proxy_pass http://127.0.0.1:3000;
    }
}

これで確かに
@nuxt/content を同梱してインストールしても
件のエラーは出なくなった。

公式

と、ここまで試行錯誤を繰り返した後で
公式に Nginx のリバースプロキシを利用する設定が載っているのを見つけた。
公式:NGINX Using NGINX as a reverse proxy


map $sent_http_content_type $expires {
    "text/html"                 epoch;
    "text/html; charset=utf-8"  epoch;
    default                     off;
}

server {
    listen          80;             # the port nginx is listening on
    server_name     your-domain;    # setup your domain here

    gzip            on;
    gzip_types      text/plain application/xml text/css application/javascript;
    gzip_min_length 1000;

    location / {
        expires $expires;

        proxy_redirect                      off;
        proxy_set_header Host               $host;
        proxy_set_header X-Real-IP          $remote_addr;
        proxy_set_header X-Forwarded-For    $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto  $scheme;
        proxy_read_timeout          1m;
        proxy_connect_timeout       1m;
        proxy_pass                          http://127.0.0.1:3000; # set the address of the Node.js instance here
    }
}

こちらで試したところ、件のエラーが出た。

WebSocket 有効化

そこで、前述の WebSocket を有効にする設定を加えた。


map $sent_http_content_type $expires {
    "text/html"                 epoch;
    "text/html; charset=utf-8"  epoch;
    default                     off;
}

server {
    listen          80;             # the port nginx is listening on
    server_name     your-domain;    # setup your domain here

    gzip            on;
    gzip_types      text/plain application/xml text/css application/javascript;
    gzip_min_length 1000;

+   proxy_http_version 1.1;
+   proxy_set_header Upgrade $http_upgrade;
+   proxy_set_header Connection "upgrade";

    location / {
        expires $expires;

        proxy_redirect                      off;
        proxy_set_header Host               $host;
        proxy_set_header X-Real-IP          $remote_addr;
        proxy_set_header X-Forwarded-For    $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto  $scheme;
        proxy_read_timeout          1m;
        proxy_connect_timeout       1m;
        proxy_pass                          http://127.0.0.1:3000; # set the address of the Node.js instance here
    }
}

エラーが出る。。。

直アクセス

curl http://localhost:3000/

と、直接アクセスしたときはエラーが出ないので
やっぱり Nginx の問題だと思われる。

リバースプロキシ排除

location ディレクティブ内のリバースプロキシの設定をコメントアウトしてみた。


map $sent_http_content_type $expires {
    "text/html"                 epoch;
    "text/html; charset=utf-8"  epoch;
    default                     off;
}

server {
    listen          80;             # the port nginx is listening on
    server_name     your-domain;    # setup your domain here

    gzip            on;
    gzip_types      text/plain application/xml text/css application/javascript;
    gzip_min_length 1000;

+   proxy_http_version 1.1;
+   proxy_set_header Upgrade $http_upgrade;
+   proxy_set_header Connection "upgrade";

    location / {
        expires $expires;

#        proxy_redirect                      off;
#        proxy_set_header Host               $host;
#        proxy_set_header X-Real-IP          $remote_addr;
#        proxy_set_header X-Forwarded-For    $proxy_add_x_forwarded_for;
#        proxy_set_header X-Forwarded-Proto  $scheme;
#        proxy_read_timeout          1m;
#        proxy_connect_timeout       1m;
        proxy_pass                          http://127.0.0.1:3000; # set the address of the Node.js instance here
    }
}

エラーが出ない!

proxy_set_header

いっぱいコメントアウトしたので、選別をしたところ


map $sent_http_content_type $expires {
    "text/html"                 epoch;
    "text/html; charset=utf-8"  epoch;
    default                     off;
}

server {
    listen          80;             # the port nginx is listening on
    server_name     your-domain;    # setup your domain here

    gzip            on;
    gzip_types      text/plain application/xml text/css application/javascript;
    gzip_min_length 1000;

+   proxy_http_version 1.1;
+   proxy_set_header Upgrade $http_upgrade;
+   proxy_set_header Connection "upgrade";

    location / {
        expires $expires;

        proxy_redirect                      off;
#        proxy_set_header Host               $host;
#        proxy_set_header X-Real-IP          $remote_addr;
#        proxy_set_header X-Forwarded-For    $proxy_add_x_forwarded_for;
#        proxy_set_header X-Forwarded-Proto  $scheme;
        proxy_read_timeout          1m;
        proxy_connect_timeout       1m;
        proxy_pass                          http://127.0.0.1:3000; # set the address of the Node.js instance here
    }
}

これならエラーが出ない。
proxy_set_header があるとエラーが出ることが判明。

リバースプロキシを location の外へ

途方に暮れていたところ
なんとなく、proxy_set_header を location ディレクティブの外へ配置してみた。


map $sent_http_content_type $expires {
    "text/html"                 epoch;
    "text/html; charset=utf-8"  epoch;
    default                     off;
}

server {
    listen          80;             # the port nginx is listening on
    server_name     your-domain;    # setup your domain here

    gzip            on;
    gzip_types      text/plain application/xml text/css application/javascript;
    gzip_min_length 1000;

+   proxy_http_version 1.1;
+   proxy_set_header Upgrade $http_upgrade;
+   proxy_set_header Connection "upgrade";

+   proxy_set_header Host               $host;
+   proxy_set_header X-Real-IP          $remote_addr;
+   proxy_set_header X-Forwarded-For    $proxy_add_x_forwarded_for;
+   proxy_set_header X-Forwarded-Proto  $scheme;

    location / {
        expires $expires;

        proxy_redirect                      off;
        proxy_read_timeout          1m;
        proxy_connect_timeout       1m;
        proxy_pass                          http://127.0.0.1:3000; # set the address of the Node.js instance here
    }
}

エラーが出ない!

解決その2???

解決したとは思えないけど
疲れたので、アプリ側を実装するまで、一旦これでよしとする。。。

参考サイト

GitHub:Websocket error using alternative server framework(2020-06-14)

PLEASE SLEEP:nginx の proxy_set_header の継承ではまった(2013-05-18)
-> 調査の過程でこんな記事も見つけたので、一応メモ。古い記事なので、今は仕様が変わっているかも

v-if の使い方(位置)

久しぶりにこのエラーに遭遇した。

エラー
TypeError: Cannot read properties of undefined (reading ‘toLowerCase’)

前回と文言が異なるのは、Nuxt の仕様変更かしらね?

原因

コメントアウトを繰り返し、箇所を特定したところ

~/components/Loader.vue

ここだった。

解決

とりあえず一個上のDOMにv-ifを移動して解決。

ハッカーになりたい!:Nuxt.jsの$route.pathは$nuxt.$route.pathを使え!(2018-09-04)

という記事を見かけたので


こうしたら、エラーが出なくなった。

言われてみれば、元のコードだと
template 直下に v-if が仕込まれているので
状況によっては、template 内が空になるコードとなっている。

これは Nuxt の仕様的に、確かアウトだったような。。。
そのせいか~ 🙄

Posted by muchag | Nuxt.js |
初回投稿:2021-03-05 (金) 18:30:39 | 最終更新:2021-10-16 (土) 11:39:52

スクリプト実行

Posted by muchag | Google Apps Script |
初回投稿:2019-11-17 (日) 10:45:17 | 最終更新:2019-11-17 (日) 10:47:05

スクリプトを実行する方法は
いくつかある。

【環境】
GAS: November 6, 2019
スクリプトエディタ

スクリプトエディタのツールボタン [関数を選択]-[(対象の関数名)] [(再生ボタン)] または Ctrl + R

ボタン
[挿入] から、画像なりテキストなりを配置して
そこへ関数を登録して、ボタンとして利用する。

ただし、ドキュメントでは、文章中にボタンが配置されてしまうので
うまく扱えなかった。

メニュー

function onOpen() {
  var ui = DocumentApp.getUi();
  var menu = ui.createMenu('スクリプトメニュー');
  menu.addItem('リスト変換', 'main');
  menu.addToUi();
}

onOpen メソッドで、当該ドライブファイルを開いたときのイベントハンドラとして
リスト追加スクリプトを記述する。

  • スプレットシート:SpreadsheetApp
  • スライド:SlideApp(かな? 未調査)
  • ドキュメント:DocumentApp
参考サイト

iwb.jp:Googleスプレッドシート Apps Scriptの3つのプログラム実行方法(2018-01-22)

Posted by muchag | Google Apps Script |
初回投稿:2019-11-17 (日) 10:45:17 | 最終更新:2019-11-17 (日) 10:47:05

AngularJS Eclipse 1.2.0

Posted by muchag | AngularJS,Eclipse,Library & PlugIn & AddIn |
初回投稿:2017-09-03 (日) 11:21:41 | 最終更新:2018-11-18 (日) 18:59:30

AngularJS 用プラグイン。
eclipse marketplace:AngularJS Eclipse

【環境】
AngularJS Eclipse: 1.2.0.201606160950
Eclipse: Oxygen (4.7)
OS: Windows10 Pro 64bit
インストール

マーケットプレイスからインストール。

適用

プロジェクトのコンテキストメニュー
[構成]-[Convert to AngularJS Project…]

Term Plugin の
[モジュール] というダイアログが出るので [適用して閉じる]

設定
検証

プロジェクトのコンテキストメニュー
[プロパティー]

左ペン [検証]-[HTML 構文] [プロジェクト固有の設定を可能にする] にチェック
[次の検証問題の重大度レベルを選択:]

要素
[不明なタグ名]-[無視] [無効なタグ名]-[無視]
属性
[未定義の属性名]-[無視] [未定義の属性値]-[無視] [適用して閉じる] [検証設定が変更されました] ダイアログがでるので [はい]
アウトライン
[ウィンドウ]-[ビューの表示]-[その他] [JavaScript]-[Tern Outline] で、専用アウトラインビューが開く。

参考サイト

Java Code Geeks:Eclipse IDE AngularJS Tutorial

Posted by muchag | AngularJS,Eclipse,Library & PlugIn & AddIn |
初回投稿:2017-09-03 (日) 11:21:41 | 最終更新:2018-11-18 (日) 18:59:30

クラス -> ES6(ES2015)

Posted by muchag | JavaScript |
初回投稿:2017-08-15 (火) 13:53:49 | 最終更新:2017-08-15 (火) 14:14:29

いよいよわかりやすい class がきた~♪

MDN:クラス

前提

まだ全然わかっていないけど、
本日あちこち読んでみて、理解したと思えることを記述。
理解が深まるに連れて、改変。

書き方も色々とあるみたいだけど
他言語とできるだけ似た形で
私が理解しやすい書式を採用。

書式
  1. class Humane {
  2.  
  3.     // コンストラクタ
  4.     constructor(name) {
  5.    
  6.         // メンバ変数(プロパティ)
  7.         this.name = name
  8.         this.age = 20;
  9.     }
  10.    
  11.     // 一般メソッド(prototype)
  12.     eat() {
  13.     }
  14.    
  15.     // 静的メソッド(static)
  16.     static sleep() {
  17.     }
  18.    
  19.     // getter
  20.     get age() {
  21.    
  22.         return this.age;
  23.     }
  24.    
  25.     // setter
  26.     set age(age) {
  27.    
  28.         this.age = age;
  29.     }
  30. }
メンバ変数(プロパティ)

メンバ変数は、コンストラクタの中へ記述。

メソッド

function キーワードを抜いて記述。

コンストラクタ

クラスがインスタンス化される際に一度だけ実行される。

一般メソッド

インスタンス化しないと利用できない。

静的メソッド

インスタンス化せずに利用する。
インスタンス化すると利用できない! らしい。。。

ユーティリティ系に利用されることが多い。

getter, setter

上記のように記述することで、クラスプロパティのように利用できる。

  1. var hayata = new Human('Hayata');
  2.  
  3. // setter を利用
  4. hayata.age = 42000;
  5.  
  6. // getter を利用
  7. var ultramanAge = hayata.age;
  8.  
  9. console.log(ultramanAge + '歳');
  10.  
  11. // 42000歳
継承
書式
  1. class Taiin extends Humane {
  2.  
  3.     constructor(name) {
  4.    
  5.         // 親クラスのコンストラクタを呼び出し
  6.         super();
  7.     }
  8.    
  9.     eat() {
  10.    
  11.         // 親クラスのメソッドを呼び出し
  12.         super.eat();
  13.     }
  14.    
  15.     change() {
  16.     }
  17. }
親クラス

親(基底、スーパー)クラスの呼び出しキーワードは super。

多重継承

できない。

参考サイト

ウェブの葉:クラス構文について[class][コンストラクタ][ES6](2017-06-03)
HTML5Experts.jp:JavaScriptにもクラスがやってきた!JavaScriptの新しいclass構文をマスターしよう(2015-10-16)

Posted by muchag | JavaScript |
初回投稿:2017-08-15 (火) 13:53:49 | 最終更新:2017-08-15 (火) 14:14:29

Module

Posted by muchag | AngularJS |
初回投稿:2016-04-17 (日) 15:38:50 | 最終更新:2017-08-15 (火) 15:06:36


公式(1.4.10):AngularJS API Docs

【環境】
AngularJS:1.4.3
ng (core module)

コアモジュール。
本体だけで事足りる。
これ以外は、必要ファイルを読み込む必要がある。

ngRoute
ngAnimate
ngAria
ngResource
ngCookies
ngTouch
ngSanitize
ngMock
Posted by muchag | AngularJS |
初回投稿:2016-04-17 (日) 15:38:50 | 最終更新:2017-08-15 (火) 15:06:36

jQuery Easing Plugin

Posted by muchag | jQuery,Library & PlugIn & AddIn |
初回投稿:2016-03-05 (土) 10:49:20 | 最終更新:2016-03-05 (土) 10:49:20


jQuery Easing Plugin (version 1.3)
最終更新日:2013-01-31

【環境】
jQuery: 1.11.3
jquery.easing.: 1.3
概要

アニメーション動作パターン集。

jQuery が持つアニメーション動作パターンを拡張してくれる。

DL

jQuery Easing Plugin (version 1.3) の Download より
jquery.easing.1.3.js のリンクをクリック。

一覧

Easing Function 早見表

Posted by muchag | jQuery,Library & PlugIn & AddIn |
初回投稿:2016-03-05 (土) 10:49:20 | 最終更新:2016-03-05 (土) 10:49:20

Photoshop -> スクリプト

Posted by muchag | JavaScript,Photoshop |
初回投稿:2016-01-06 (水) 13:00:11 | 最終更新:2016-02-19 (金) 20:02:30

Adobe 製品を Javascript で制御できるそうな。
素敵~。

【環境】
Photoshop:CS6
OS:Windows 7 SP1 64bit
実行
[ファイル]-[スクリプト]-[参照] JSX ファイルを選択して [読み込み]
デバッグ

上記実行行程の [読み込み] をクリックする際に
Alt を押しながらで、デバッグウィンドウが開く。

layers, artLayers

よくわからないので、スクリプトを書いて検証中。
現在のところ、下記のような感じ。
正解は不明。
layers:第1階層のレイヤー(グループディレクトリもレイヤーとしてカウント)
artLayers:第1階層の画像を含むレイヤー

テキストレイヤー

Photoshopでテキストレイヤーを作成するスクリプト

ExtendScript Toolkit
コンソール

JavaScript コンソールへ出力する方法。

  1. $.write('hoge');
  2. $.writeln('moge'); // 改行あり
マクロ記録

Excel VBA のときに散々お世話になった「マクロ記録」。
Photoshop にもあった~♪

概要

Scripting Listener というプラグインを利用する。

DL

各紹介記事では
公式ヘルプ:Photoshop CC アドオン(プラグインおよび拡張機能)
から DL と紹介されているけど、実際は、上記ページの下部「ダウンロード可能な内容」をクリックして
Photoshop Help:Downloadable plug-ins & content | Photoshop CC
へ飛び、ScriptingListener plug-in から DL。

2016-02-19 現在
Win_Scripting_Plug-In.zip(Windows 用)

配置

アプリケーションディレクトリ(32bit か 64bit 次第)を photosho と称する。

  1. Win_Scripting_Plug-In
  2. └─Scripting_Win32(または Scripting_Win64)
  3.     ├─Documents
  4.     │      略
  5.     │
  6.     ├─Sample Scripts
  7.     │  ├─AppleScript
  8.     │  │      略
  9.     │  │
  10.     │  ├─JavaScript
  11.     │  │      略
  12.     │  │      ScriptListenerOff.jsx → photosho\Presets\Scripts
  13.     │  │      ScriptListenerOn.jsx → photosho\Presets\Scripts
  14.     │  │      略
  15.     │  │
  16.     │  └─VBScript
  17.     │          略
  18.     │
  19.     └─Scripting Utilities
  20.             ScriptListener.8li → photosho\Plug-ins
再起動

Photoshop を起動中であれば再起動。

利用

これで、[ファイル]-[スクリプト] に

  • ScriptListenerOff
  • ScriptListenerOn

が表示されるようになるので
記録を開始したいときに On を、終了したいときに Off を選択すればよい。

記録結果

記録内容は、デスクトップに

ScriptingListenerJS.log

というファイルが生成される。

追記式なので、必要に応じてファイルをコピーして
本体ファイルのテキストをクリアすること。

参考サイト

Adobe:API Documentation com.adobe.photoshop

Adobe Photoshop CS6自動化作戦
→サンプルスクリプトがいっぱい♪

Adobe CS1〜C6, CC バージョンJavaScript リファレンス&ライブラリ

Google ブックス:Photoshop自動化基本編
→これなんだろ。。。抜粋でなくて全部読めるっぽい。

Posted by muchag | JavaScript,Photoshop |
初回投稿:2016-01-06 (水) 13:00:11 | 最終更新:2016-02-19 (金) 20:02:30

関数名を文字列で指定して実行する

Posted by muchag | JavaScript |
初回投稿:2015-12-30 (水) 15:13:45 | 最終更新:2015-12-30 (水) 15:20:04

PHP では、$$hoge という書き方があって便利なんだけど
Javascript ではどうやるのかな~って探してみた。

下記サンプルコードは、参考サイトより引用させていただきました。

eval

メソッド名を文字列で組み立てて
eval してやることで、関数として「評価」してくれる
ということらしい。率直だ!

  1. var word="apple";
  2. function orange(){
  3.     alert("ミカン");
  4. }
  5. function apple(){
  6.     alert("リンゴ");
  7. }
  8. eval(word+"()");
関数連想配列

私はこちらの方がピンときたので、こちらを採用させていただいた。

  1. var myfunction = [];
  2. myfunction["tashi"] = function (a, b) {
  3.     return a + b;
  4. }
  5. myfunction["hiki"] = function (a, b) {
  6.     return a - b;
  7. }
  8. alert(myfunction["tashi"](2, 5));
参考サイト

You Look Too Cool
evalを使わずに関数を文字列で指定して実行する方法
文字列で関数を実行する

Posted by muchag | JavaScript |
初回投稿:2015-12-30 (水) 15:13:45 | 最終更新:2015-12-30 (水) 15:20:04

jsTree

Posted by muchag | jQuery,Library & PlugIn & AddIn |
初回投稿:2015-10-28 (水) 14:21:48 | 最終更新:2015-11-19 (木) 15:42:09

ひさびさにツリーメニューを実装しようと思って
Treeview を設置してみたけど、動かない。。。
更新も止まっているようだし、他のプラグインを探してみたら良さそうなのがあった。 😯
採用するかどうかはわからないけど、使い方をメモ。

コード中に出てくる vakata って何かと思ってたけど
作者の HN でした。
GitHub:vakata

【環境】
jsTree:3.2.1
jQuery:1.11.3
DL

公式 の Download ボタンより DL。
2015-10-28 現在
vakata-jstree-3.2.1-0-g8ea6ce7.zip

ファイル配置
  1. DL したファイルを解凍
  2. 中身の dist ディレクトリを js ディレクトリへ配置
  3. 配置した dist ディレクトリを jstree にリネーム

中には CSS ファイルや画像ファイルもあるので、本来なら分けるべきかもしれないけど、ここで完結させる。
なぜなら、テーマ名を設定するだけで、テーマの変更をできるようになっているから。
でも、その割には CSS ファイルへの参照はちゃんと記述しないとダメ。。。

利用
前提
  1. <link rel="stylesheet" type="text/css" href="./css/jstree.min.css">
  2. <script type="text/javascript" src="./js/jquery-1.11.3.min.js"></script>
  3. <script type="text/javascript" src="./js/jstree.min.js"></script>
リストタグ
  1. <script>
  2. $(document).ready(function(){
  3.       $('#tree').jstree();
  4. });
  5. </script>
  6.  
  7. <div id="tree">
  8. <ul>
  9.     <li>階層1
  10.     <ul>
  11.         <li>階層2</li>
  12.     </ul>
  13.     </li>
  14. </ul>
  15. </div>

注意
階層リストの場合、書式に注意。
下記タイプA、タイプB、どちらでもリスト表示をできるけど
jsTree は、タイプB で記述しないと認識しない。

  1. // タイプA
  2. <ul>
  3.     <li>階層1</li>
  4.     <ul>
  5.         <li>階層2</li>
  6.     </ul>
  7. </ul>
  8.  
  9. // タイプB
  10. <ul>
  11.     <li>階層1
  12.     <ul>
  13.         <li>階層2</li>
  14.     </ul>
  15.     </li>
  16. </ul>

私は今までタイプAで書くのが普通だったんだけど
もしかして、正式はタイプBなのかしら。。。汗

XML データ
JSON データ
注意

ツリー項目に a タグを付けてリンクを貼ろうとしたけど
どうも表示が変になる。

  1. <li>Content <a href="#">Edit</a></li>

としても、Edit だけが表示される。

dnd の研究にノードオブジェクトの中身を覗いてみたけど
jsTree が表示用に a タグを利用しているようで
リンクを貼りたければ、click イベントで制御するしかなさそう。

設定書式

プラグインも含めた設定の例。

  1. $(document).ready(function(){
  2.     $('#jstree').jstree({
  3.         // 基本設定
  4.         'core' : {
  5.             'themes' : {
  6.                 'variant' : 'large'
  7.             }
  8.         },
  9.         // プラグイン毎の設定
  10.         'checkbox' : {
  11.             'keep_selected_style' : false
  12.         },
  13.         // 利用するプラグインを列挙?
  14.         'plugins' : [ 'wholerow', 'checkbox' ]
  15.     });
  16. });
  17. </script>

こんな感じ。
他のプラグインと同じ~。 😯

‘plugins’ で、On にしたいプラグインを列挙し
プラグイン毎の設定で、各プラグインの設定変更をする。

設定変更がなければ、プラグイン各個の設定は記述しなくて良い。

core(基本設定)
themes
  1. $(document).ready(function(){
  2.     $('#jstree').jstree({
  3.         "core" : {
  4.             'themes' : {
  5.                 // 独自テーマを利用したい場合は、当該ディレクトリ名文字列を指定?
  6.                 'name' : false,
  7.                 // 独自テーマを利用したくて、.js ファイルと別階層に置きたい場合に true を指定?
  8.                 'url' : false,
  9.                 // url を true にしたときだけ有効。テーマの場所を記述?
  10.                 'dir' : false,
  11.                 // ツリー罫線を表示するか否か
  12.                 'dots' : true,
  13.                 // ノード(フォルダ)アイコンを表示するか否か
  14.                 'icons' : true,
  15.                 // 1行おきに背景色を付けて縞々にするか否か
  16.                 'stripes' : false,
  17.                 // CSS クラス('large', 'small', 'responsive')があるっぽい
  18.                 // false でデフォルトなんだろうけど、どれかわからない
  19.                 'variant' : false,
  20.                 // 小さい画面の時は ture って書いてある気がするけど、true にしてみても、違いがわからない
  21.                 'responsive' : false,
  22.             }
  23.         }
  24.     });
  25. });
check_callback

ユーザーによるツリーの変更を許可するか否か。
デフォルトは false。

  1. $(document).ready(function(){
  2.     $('#jstree').jstree({
  3.         "core" : {
  4.             'check_callback' : false,
  5.         }
  6.     });
  7. });
関数指定

true か false か、状況によって変化させるために
関数を指定することができる。

  1. $(document).ready(function(){
  2.     $('#jstree').jstree({
  3.         "core" : {
  4.             'check_callback' : function (operation, node, node_parent, node_position, more) {
  5.                 if ((operation === 'move_node' || operation === 'copy_node') && (node_parent.id === '#')) return false;
  6.             },
  7.         }
  8.     });
  9. });
jstree.js
  1. * __Examples__
  2. *
  3. *   $('#tree').jstree({
  4. *       'core' : {
  5. *           'check_callback' : function (operation, node, node_parent, node_position, more) {
  6. *               // operation can be 'create_node', 'rename_node', 'delete_node', 'move_node' or 'copy_node'
  7. *               // in case of 'rename_node' node_position is filled with the new node name
  8. *               return operation === 'rename_node' ? true : false;
  9. *           }
  10. *       }
  11. *   });
引数
jstree.js
  1. * @name check(chk, obj, par, pos)
  2. * @param  {String} chk the operation to check, can be "create_node", "rename_node", "delete_node", "copy_node" or "move_node"
  3. * @param  {mixed} obj the node
  4. * @param  {mixed} par the parent
  5. * @param  {mixed} pos the position to insert at, or if "rename_node" - the new name
  6. * @param  {mixed} more some various additional information, for example if a "move_node" operations is triggered by DND this will be the hovered node
  7. * @return {Boolean}
  • 引数
    • operation(String)
      • ソース説明の通り。5種
    • node(Object)
      • オブジェクト
    • node_parent(Object)
      • 移動先の親オブジェクト
    • node_position(integer)
    • more(Object)
      • core
      • is_foreign
      • is_multi
      • origin(Object)
        • 恐らく移動前のツリー全体の情報が格納されている
        • 参考記事の more.ref.data.type の使い方不明
よくわからないオブジェクト連鎖

stackoverflow:JsTree v3.0 drag and drop plugin. Reference target node upon dropping
こちらに書かれている下記コードにおける
more.ref.data.type
が、何をどう辿っているのか不明。

  1. if (more.ref.data.type === "folder") {
  2.     return true;
  3. }
  1. console.log(more.ref.data.type);
TypeError: more.ref is undefined
タイミング

チェックは常に行っているらしく
上記のように指定することで、ドラッグ中に
root 直下へは、移動先候補 ▶ のマークが出なくなった。

data(Ajax)

こちらを設定しておくことで、ページ読み込み時に
そちらを読みにいく。

  1. $(document).ready(function(){
  2.     $('#jstree').jstree({
  3.         "core" : {
  4.             'data' : {
  5.                 'url' : function (node){
  6.                             if (node.id === '#') {
  7.                         return "http://localhost:9000/getCourses/" ;
  8.                             }
  9.                             else
  10.                         return "http://localhost:9000/getCourses/" + node.id;
  11.                             }
  12.                         },
  13.                 'data' : function (node) {
  14.                             return { 'id' : node.id };
  15.                         }
  16.             }
  17.         }
  18.     });
  19. });

こちらは下記サイトのコードをいただいてきたが
あちこちでこのような書き方がされている。
answer uxu:jstree html and json

どうもデフォルトでは、node.id がルートの # になっていて
ルートの情報を取得して表示。
後はノードを選択する度に、そのノードの ID を送り、その配下の情報を取得し表示。
という仕様になっているっぽい。

変更の通信ではない?

プラグイン

jsTree という名前の jQuery プラグインに実装されている
プラグイン(追加機能)。

一覧

公式:Plugins?

  1. 'plugins' : [
  2.     'checkbox',
  3.     'contextmenu',
  4.     'dnd',
  5.     'massload',
  6.     'search',
  7.     'sort',
  8.     'state',
  9.     'types',
  10.     'unique',
  11.     'wholerow',
  12.     'changed',
  13.     'conditionalselect'
  14. ]
checkbox
設定
  1. $(document).ready(function(){
  2.     $('#jstree').jstree({
  3.         'checkbox' : {
  4.             // 選択された行に背景色をつけるか否か
  5.             'keep_selected_style' : true
  6.         }
  7.         'plugins' : [ 'checkbox' ]
  8.     });
  9. });
contextmenu

contextmenu

dnd(Drag and Drop)

dnd(Drag and Drop)

search
設定

JSFIDDLE:http://jsfiddle.net/53cvtbv9/1/

  1. $(document).ready(function(){
  2.     $('#jstree').jstree({
  3.         'plugins' : [ 'search' ]
  4.     });
  5. });
  1. <div><?php echo __('Search : '); ?><input type="text" class="search-input" /></div>
  2.  
  3. <script>
  4. $(document).ready(function() {
  5.     $(".search-input").keyup(function() {
  6.         var searchString = $(this).val();
  7.         $(selectorTree).jstree('search', searchString);
  8.     });
  9. });
  10. <script>
unique

単一ノード直下の重複チェック。

設定
  1. $(document).ready(function(){
  2.     $('#jstree').jstree({
  3.         'unique' : {
  4.             // 大文字小文字の区別をするか否か
  5.             'case_sensitive' : false,
  6.             // 重複した場合の名称を hoge -> hoge (2) のように変更する
  7.             'duplicate' : false,
  8.         }
  9.         'plugins' : [ 'unique' ]
  10.     });
  11. });
イベントリスナー

イベントリスナー

メソッド
書式

複数あるっぽい。

  1. $('#jstree').jstree('select_all'); // うまくいった
  2. $('#jstree').select_all(true); // 未試行
一覧
  1. // 選択系
  2. $('#jstree').jstree('select_all'); // 全選択
  3. $('#jstree').jstree('check_all'); // 全選択
  4. $('#jstree').jstree('deselect_all'); // 全選択解除
  5.  
  6. $('#jstree').jstree('select_node', node.id); // 個別選択
  7. $('#jstree').jstree('deselect_node', node.id); // 個別選択解除
  8.  
  9. // オープン系
  10. $('#jstree').jstree('open_all'); // 全開く
  11. $('#jstree').jstree('close_all'); // 全閉じる
  12. // 後はパターンで考えてましょう。。。
本体解析
this

全部でないかもしれないけど、本体コード中に現れる this は
カスタマイズの際には $(selectorTree).jstree(true) に読みかえればよいかも?

Loading

本体の Ajax 通信を利用せずに、独自の通信ロジックにしたら
Loading 表示のやり方がわからなかった。

独自にした理由

どこの例を見ても、’data’ : のところが、{ “id” : node.id } となっていて、それ以外のデータの渡し方がわからなかったから
当該ノードだけを更新するわけでなくて、ツリー全体を更新しているから

本体解析

うまい例を見つけられなかったので、本体を見てみた。

jstree.js
  1. refresh : function (skip_loading, forget_state) {
  2.  
  3.     __snip__
  4.  
  5.     if(!skip_loading) {
  6.         this.element.html("<"+"ul class='"+c+"' role='group'><"+"li class='jstree-initial-node jstree-loading jstree-leaf jstree-last' role='treeitem' id='j"+this._id+"_loading'><i class='jstree-icon jstree-ocl'></i><"+"a class='jstree-anchor' href='#'><i class='jstree-icon jstree-themeicon-hidden'></i>" + this.get_string("Loading ...") + "</a></li></ul>");
  7.         this.element.attr('aria-activedescendant','j'+this._id+'_loading');
  8.     }
  9.  
  10.     __snip__
  11. }

どうやら、ここで表示しているらしい。

本体の HTML を一旦 Loading 用に書き換えちゃってるのね~。

refresh

それで、いくつか refresh メソッドを試してみたけど表示されなかった。

  1. $(selectorTree).jstree(true).trigger('refresh');
  2.  
  3. // create で試したけど、当該ノードが消えただけ
  4. // refresh をかけたわけだから、create に前に戻るので当たり前
  5. $(selectorTree).jstree(true).refresh();
Loading 表示

上記の HTML の内、わからないところとか、不必要と思われる箇所を少しだけ除いて
無理くり下記のようにしてみたら、ツリー全体を Loading 画像で置き換えることができた。

  1. var htmlLoading = '<ul class="jstree-container-ul jstree-children" role="group">'
  2. + '<li class="jstree-initial-node jstree-loading jstree-leaf jstree-last" role="tree-item">'
  3. + '<i class="jstree-icon jstree-ocl"></i>'
  4. + '<a class="jstree-anchor" href="#">'
  5. + '<i class="jstree-icon jstree-themeicon-hidden"></i>Loading ...'
  6. + '</a>'
  7. + '</li>'
  8. + '</ul>';
  9.  
  10. $('#jstree').jstree(true).element.html(htmlLoading);
refresh

そのまんま。
読み込んだときの状態に戻す。

  1. $(selectorTree).jstree(true).refresh();
  2.  
  3. $(selectorTree).jstree(true).refresh(false, false);

第1引数:skip_loading。Loading 表示をスキップするか否か
第2引数:forget_state。現状を記憶するか否か

参考サイト

株式会社アンフィニ 技術ブログ:【javascript】jQueryプラグイン jsTreeの紹介
海外製ライブラリ・Web API ドキュメントの翻訳ページ:jsTreeドキュメント日本語訳

Posted by muchag | jQuery,Library & PlugIn & AddIn |
初回投稿:2015-10-28 (水) 14:21:48 | 最終更新:2015-11-19 (木) 15:42:09

UI -> dialog

Posted by muchag | jQuery |
初回投稿:2015-04-07 (火) 16:53:37 | 最終更新:2015-04-07 (火) 17:00:05

ダイアログウィジェット。

jQuery UI:Dialog Widget

ボタン要素
テキスト
  1. buttons: {
  2.     'AAA': function( event ) {
  3.         if ( $( event.target ).text() == 'AAA' ) {
  4.             $( event.target ).text( 'XXX' );
  5.         }
  6.         else if ( $( event.target ).text() == 'XXX' ) {
  7.             $( event.target ).text( 'AAA' );
  8.         }
  9.     },
  10.     'キャンセル': function() {
  11.         $( this ).dialog( 'close' );
  12.     }
  13. },

これで、ボタンをクリックする毎にテキストを入れ替えることができた。
けど、ボタンのサイズが。。。ちっちゃくなっちゃった。。。

参考サイト

StackTrace jQuery UI API 1.8.4 日本語リファレンス:Dialog
→ボタンテキストの取得はこちらを参考にさせていただいた
js STUDIO:Dialog
jQuery UI の使い方:dialog(options)
Qiita:Dialogのボタンそれぞれにclassを設定する
→ボタンのオプション指定について、他とは異なった書式が紹介されている

Posted by muchag | jQuery |
初回投稿:2015-04-07 (火) 16:53:37 | 最終更新:2015-04-07 (火) 17:00:05
次ページへ »