Ajaxに悩んだ二年間

現代のWeb PageはAjax通信を用いてページの書き換え無しに表示データを更新する仕組みが広く使われています。Ajax = Asynchronous JavaScript and XMLという訳の分からない言葉の頭文字をつなげた造語です。Ajaxが提唱されたのは、古く Internet Explorer5.0の時代に遡ります。ここいら辺に関しては、やはり Microsoft社とIBM社の功績が大きいようです。このIBMのエンジニアが投稿されたブログに詳しく書かれています。

僕もjQueryを用いてこのAjaxという仕組みを用い、データをデータベースから読み出しそれを用いてホームページのDOMを書き換え、動的にページを画面更新無く刷新するようなページをいくつも作成してきました。実はこれもIBMのエンジニアのブログを読んで出来るようになったのです。

さて、jQuery + PHP + MySQLを用いたAjaxはこれまでに色々なサイトで作成してきました。そのほとんどは期待した通りに動作してきたのですが、一つだけ躓く場面があったのです。現在の鎌倉ライブHpは2017年に原型を作り、それを踏襲してきたのですが、基本的概念は、Web上のMySQL databaseにデータを入力して、ユーザー・ページではその databaseからデータを読み出してHpに反映する、そのようにしたのです。

もちろん DBにデータ入力する時にはPWで保護された部分にアクセスし、一般ではアクセスできないようにしています。この時問題となったのは、下記のプログラム部分です。それが不思議なことにうまく行ったり、行かなかったりするのです。

 function ajax_search() {
$( "#search_results" ).show();
var search_val = $( "#search_term" ).val();

$.post( "tri_chair_mod_add01new_backend.php", {
    search_term: search_val
}, function ( data ) {
    if ( data.length > 0 ) {
        $( "#search_results" ).html( data );
    }
} );

  }

これが時にうまく動作して時に動作しないのです。この原因についてどうしても難しすぎて分からなかったのですが、色々考えている内に、Ajaxとは Asynchronous (=非同期)とうのが本質だと思ったのです。Web pageは非同期で表示していかないとユーザーが待たされることになります。ですから、ある画面を描く時にも、あるいはデータを受け取る時にもどちらかがどちらかの完了を待つ(=同期)することが無く、どんどん進んで行くのです。これが原因ではないかと思いました。そこで以下のように変更したのです。

  function ajax_search() {
$( "#search_results" ).show();
var search_val = $( "#search_term" ).val();
        $.ajax({
            type: 'POST',
            url: "tri_chair_mod_add01new_backend.php",
            dataType: 'html',
            data: {
                search_term: search_val
            },
            async: false,
            success: function(data) {
                if ( data.length > 0 ) {
       $( "#search_results" ).html( data );
                }
            },
            error: function(XMLHttpRequest, textStatus, errorThrown) {
                alert("Ajax error happened!");
            }
        });
  }

つまり、Ajaxのdefaultである async: trueというのを敢えて async: falseにしたのです。つまり同期をとるようにしたのです。これで長年の懸案が解決しました。とっても難しい概念です。

jQuery libraryの読み込み判定

jQueryや bootstrapは CDNよりそのソースコードを読み込むのが常道です。これには理由があり、まず CDNはライブラリ読み込みに最適化されているので、自分のサーバーから読み込むよりも早い、そしてCDNより読み込めば プログラムの置かれている階層によらず読み込み先を変更する必要が無い、というものです。

ただ、localhostでインターネット接続せずにプログラムを書いていると CDNから読み込めずにプログラムが作動しなくなることもあります。localhostで開発している時にはこれでは困ります。そんな時に、インターネット接続しているか否かで自動判定すれば助かります。そのコードとしては、

 

<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
<script>if (jQuery) document.write('<script src="lib/jquery.js"><\/script>');</script>

としたり、あるいは jQueryが既に読み込まれているか否かの判定として以下のようにするか

<script>window.jQuery||document.write('<script src="lib/jquery.js"><\/script>');</script><

とするか、あるいは phpを走らせて

<?php
  if ($_SERVER['SERVER_NAME'] === 'locallhost'
?>

として localhostかどうかを判定する、という方法がありますね

こっ これは便利だ – ChromeやFireFoxをコマンドラインより起動する

Visual Studio Codeを editorにして JavaScriptの勉強をしているのですが、なかなか思いどおりに行きません

何が思いどおりにいかないか? と言えば JavaScriptプログラム単独を走らせるのは

$node sample.js

などのようにすれば、sample.jsというプログラムが走ります そしてこの場合の出力は console.log( )で書き出し、consoleに出力します

しかし、JavaScriptと言えば、やはりブラウザとの連携です そして DOMの操作です、そうなると 例えば index.htmlをブラウザ立ち上げてその中で JavaScript fileを読み込んで走らせる、そのような運用になります ところが、いちいちこれをブラウザより行うのは面倒です どうにかして VS Code内部でできないのか? と色々考えたり、調べたりしてついに見つけました

Chromeの場合には

$open -a Google\ Chrome index.htm

FireFoxの場合には

$open -a firefox index.html

これで良いのです 実は Safariの場合には

$open -a safari index.html

これで一発で該当するブラウザでそのページが開かれ、そして JavaScriptが走ります なんて便利なんだろう

しかし、Chromeだけ Google\ Chromeとせねばならないのは許しがたいですね この場合、リンクを貼るしか無いでしょう

土日は JavaScriptに費やして

JavaScriptはとても奥が深い言語です 「単なるスクリプト言語でしょ」とか、「どうせ Browserに付属しているものでしょ」、あるいは「オブジェクト指向言語といっても、prototypeなどというものを使うのでしょ」などと酷評されることが多い言語で、僕も最初はそのように思っていました

しかし、この言語は Browserという縛りから解き放たれた時には、ものすごい能力を発揮します その部分の勉強を初めたのですが、これがとても難解です 特に今まで知らなかった関数型プログラミング、これはすごい世界です 関数型プログラミングに限らず何というか物事に対する考え方が今までと異なるので、その新して世界、文化になかなか馴染めないのですね きっと若い人にとっては何でもなく乗り越えることのできる壁なのでしょう 頑張りたいと思います

さて、今朝 12月10日は月曜日 いよいよ鎌倉ライブの週となりました そして僕は早朝といってもそんなには早くありませんが、7:00AMに自宅を歩いて出発、大船駅まで行き、現在東海道線グリー車に 1,030円支払って搭乗しています これからさる新規ディバイス治験のための会合があるのです 会合といっても本当に立ち上げなので少人数の集まりです 今日はこの会合で一日が終わりますね

でも自分の限られた時間をこのような未来に向けて投資する(消費する)ことを続けて行かないと未来は限られたものになってしまいます JavaScriptの勉強も同じ範疇のものです

知らなかった JSONでは ‘ を用いず、 ” を用いねばならない

最近のデータ表現形式では JSONを用いることが多くなっていると思います 何故ならば xmlのように冗長なものでなく、さらに各種言語で JSONを解読するルーチン (Parser)が言語の中に実装されているからです

しかし、これまで知らなかったのですが、たとえば

{
  "name": "saito",
  "age": 68,
  "sex": "M"
}

というものは JSONとして正しいのですが、一方

{
  "name": 'saito',
  "age": 68,
  "sex": 'M'
}

はエラーとなります

何が違うのでしょうか? 現在使用されているほとんどの言語では、文字列を囲む “文字列”と、’文字列’はほとんど同一です もちろん、言語によっては “”では変数を展開できるとか 細かい点では違うのですが、何れにしてもこの ダブル・クオーテーションでくくったもの文字列で、 シングル・クオーテーションでくくっても同じ文字列となるのです

ところが、JSONではダブル・クオーテーションしか認められていないのです この事実には結構皆ハマっているようです 僕も知りませんでした

久しぶりにTAVIを行いました

本日は朝から札幌東徳洲会病院心臓センターで三件のTAVIがあり、その中の一例を治療させて頂きました

北海道地震の被害からも立ち直りTAVIが本格的に再開されたのです 僕が治療させて頂いたのは、ご高齢の方でしたが、かなり高度な大動脈弁狭窄症であり、治療してよかったと思います 9:30AMよりTAVIのセッションが開始となり、合計で三例の治療を終わったのは 14:00でした 縦に三例を4.5時間半で入れ替えなども含んでする、というのは相当に早いですよね 入れ替え時間を含め、麻酔も含めて一例 1.5時間ということになります 素晴らしいですね

長期間の海外出張で、しかも西に東にですので、相当に体のリズムが狂ってしまいましたが、徐々に回復です とは言っても色々なメールには応答できていません 頭が回りません

頭のリハビリには Javascriptの勉強をしています Javascriptと言っても、正確には ECMAScript20151 というもので、別名 ES6と呼ばれている言語仕様のものです 現在ではほとんどのブラウザ上にこの ES6は実装されていますし、node.jsにも実装されています

言語仕様は非常に先進的なものであり、これまでのプログラミングの大きな考え方 (= パラダイム)を変更するほどのインパクトがあります 際立って紹介されているのが、アロー演算子とか Promiseとかいうものです Promiseに関しては未だ勉強を開始していません 現在はアロー演算子の習得にかかっています

/*jslint node: true */
/*jshint esversion: 6 */
"use strict";

const ary = [1, 4, 7, 9, 32, 43];
let reducer = (accumulator, initialValue) => accumulator + initialValue;
let result = ary.reduce(reducer);
console.log(result);

ここで、最初の2つのコメント欄が無いと、jslintという文法チェッカーでエラーを吐かれます

このプログラムは、配列の合計を求めるという他愛もないものですが、重大なパラダイムシフトがあるのです とっても難しいのですよ

こっ こっ こっ これは素晴らしい

javascriptは関数型言語として捉えるとものすごく先進的な言語であるらしいのです もっとも ECMA Script 6 (ES6)あるいは  ECMAScript2015とも呼ばれるもの以降の話のようですが・・・

てなわけで少しだけ勉強しようと思っているのですが、何はともあれ javascript実行環境が無いと練習できません もちろんそのような意味では各種Browserには javascriptが内蔵されているのでそこで consoleを叩けば良いのですが、なかなか面倒ですよね

あるいは $node としてnode.jsを立ち上げその中で実行するのもありですが、これは文ごとでの実行となり今一つですよね

ところが VSCodeでは簡単に実行できることが分かりました もちろん node.jsがインストールされていないと駄目なのでしょうかね なかなか素晴らしいですよ

ついに RAP and BEATのトップページに実装

これまでの積み重ねを経て、各種テストを行いました そして ついに RAP and BEATのトップページに登録症例数のグラフ表示を実装できました

動画で表示するようにし、自施設に関しては、赤グラフで表示するようにしました もちろん、ログインが誰により行われ、その人が所属する施設が自施設となります ここで問題だったのは、$_SESSION変数を如何にして Javascriptライブラリである D3.jsに変数として渡すか? でしたが これに関しては少し調べて簡単にできることが分かりました

ここに記載されていたように json_encodeを用いて jsonオブジェクトとして渡すのだそうです これは securityが深く関係しているようです 実際の javascript codeはかくも簡単です

// json_encodeを使用して$_SESSION変数を安全に javascript変数に変換する
    var hp_tbl_id = <?php echo json_encode($_SESSION['hp_tbl_id'], JSON_HEX_TAG | JSON_HEX_AMP | JSON_HEX_APOS | JSON_HEX_QUOT); ?>;

この関数の第二引数はオプションであり、security上非常に重要だそうです

こんな馬鹿なことで1週間潰した

さて、今から本格的にプログラム書こうと思っているのが、2019年に学会長を行うように指示されといるとある学会があるのですが、そのいわゆる学会プログラムやその他諸々を handlingするソフトの開発なのです 当然のことながら Smart Phone/Tablet/PCの全てに対応するように “Responsive Web Design”で開発するのです DBは慣れている MySQLを使用し、言語もこれも慣れている PHPを使用します

こんものいちなり書けないのでテスト・プログラムを作成し、local web serverでテスト繰り返すのですが全く作動しないのです

「えーーっ、なんでぇーーー こんな筈は無いはずだあ」と一週間悩んだのです 少しずつ修正しながらテストするのですが全く僕の意図を無視して動作しないのです

まあこんな感じです

// ここれはフロントエンドで SQLに探索語を渡す Ajax通信のルーチン
    $( document ).ready( function () {
      $( "#search_results" ).slideUp();
      $( "#search_term" ).keyup( function ( e ) {
        e.preventDefault();
        ajax_search();
      } );

      function ajax_search() {
        $( "#search_results" ).show();
        var search_val = $( "#search_term" ).val();
        $.post( "dr_role_find_backend.php", {
          search_term: search_val
        }, function ( data ) {
          if ( data.length > 0 ) {
            $( "#search_results" ).html( data );
          }
        } );
      }
    } );

 

そして受け取る方は、PHPとMySQLです

 session_start();
 session_regenerate_id(true);
 require_once('../utilities/config.php');
 require_once('../utilities/lib.php');	
 charSetUTF8();
 //接続
	try {
   // MySQLサーバへ接続
  	$pdo = new PDO("mysql:host=$db_host;dbname=$db_name_sessions;charset=utf8", $db_user, $db_password);
 // 注意: 不要なspaceを挿入すると' $db_host'のようにみなされ、エラーとなる
 } catch(PDOException $e){
   		die($e-&gt;getMessage());
 }

 $hp_name = strip_tags(trimBothEndSpace(mb_substr($_POST['search_term'], 0, 100)));	// 前後のspaceなど削除し、文字数を100文字に制限する
 $hp_name = strtoupper(mb_convert_kana($hp_name, 'ashK'));		// 半角英字大文字に変換する

 $stmt = $pdo-&gt;prepare("SELECT * FROM `hp_tbls` WHERE `hp_name` LIKE :hp_name ORDER BY `hp_name` ASC;");
 $stmt-&gt;bindValue(":hp_name", '%'.$hp_name.'%', PDO::PARAM_STR);
 $flag = $stmt-&gt;execute();
 $rows = $stmt-&gt;fetchAll(PDO::FETCH_ASSOC);
 
 if (!$flag) {
   		$infor = $stmt-&gt;errorInfo();
     exit($infor[2]);
 }

 

これで、検索語として病院名の一部を入力すれば、DBより検索してくれる筈なのです

しかし、しかし動作しない 本当にこの解決に一週間かかり、先程やっと解決しました

色々な問題があったのです まずは

trimBothEndSpace(mb_substr($_POST['search_term'], 0, 100))

という関数ですが、(1) mb_substrの引数を何時の間にか消去してました つぎに(2) trimBothEndSpaceという関数ですが、これは自作関数なのですが、それをlib.phpに作成してあり(ある筈)、それを読み込んで使用するのですが、何と lib.phpの中にこの関数を書いていなかったのです

この2つのバグのために、phpそのものが走らず結果的に echoで途中経過を出そうと思っても出せない そんな事態に陥っていたのです 本当に大変なバグ退治でした これも Ajax通信によるプログラムだからのことです 本当に非同期通信というのは難しいです これが解決してうまく動作しているデモ画面です

うまく Ajax通信が動作しているところ