【jQuery】2つのテーブルの高さを揃える

2つのテーブルを並べて1つのテーブルに見せたい場合、
片方のテーブルのセルに内容を詰め込みすぎると、改行の都合で2テーブルの高さがずれてしまうことがあります。
こうした自体を避けるため、2つのテーブルの高さを同期させるスクリプトを描いたので載せておきます

$(function(){
    'use strict';

    var table1_tr = $("#table1 tr");
    var table2_tr = $("#table2 tr");
    for(var i=0, l=table1_tr.length; i<l;i++ ){
        var table1_cells = table1_tr.eq(i).children();
        var table2_cells = table2_tr.eq(i).children();

        var table1_cells_height = table1_cells.height();
        var table2_cells_height = table2_cellss.height();
        if(table1_cells_height > table2_cells_height){
            table2_cells.height(table1_cells_height);
        } else if(table2_cells_height > table1_cells_height){
            table1_cells.height(table2_cells_height);
        }
    }
});

やっていることを簡潔にまとめると

  • 2つのテーブルの一番上から順に行を取得
  • 取得した行の高さを比較
  • 高い方に合わせる

ということです。

.eq(i)はセレクターに該当する要素でi番目に登場しているもの、という意味で
今回の場合はtable1のi番目のtrという意味になります。

【CakePHP】テキストデータの改行を反映させるには

データベースからテキストデータを引っ張り出してきて、ビューで表示させるには
このように書くことが多いと思います。

・コントローラの場合

public function index() 
{ $this->set('items', $this->Item->find('all')); }

・ビューの場合

<?php foreach ($items as $item): ?>
  <?php echo $item['Item']['comment']; ?>
<?php endforeach; ?>

この場合'comment’というフィールドのデータが表示されるわけですが
データ中の改行が反映されないという問題点があります。

これを解決するにはモデルに
afterfind()というコールバック関数を定義します。

public function afterFind($results, $primary = false) 
{ $num_record = count($results); for($i = 0; $i< $num_record; $i++){ $results[$i]['Item']['comment'] = str_replace("\n", "</br>", $results[$i]['Item']['comment']); } return $results; }

afterfind()はfindの後で勝手に呼び出される関数で、
findした結果を配列$reslutsで受け取ります。

各レコードの"comment"フィールドの値にたいして、
改行文字を</br>で置き換える処理を行えば最終的に表示される内容を
改行することが出来ます。

 

 

 

【CakePHP】ajaxでpostする方法(2)

前回ajaxを使ってpostする方法について書きました。

【jquery】ajaxでpostする方法 - kento0824jp’s diary

こちらで紹介した方法は jQuery.post()というメソッドを使うものでしたが、
通信成功時と失敗時で処理をわけられないというデメリットが有りました。

今回は jQuery.ajax()というメソッドの使い方を紹介します。
こちらは成功、失敗で処理を分岐させることが出来ます。

$.ajax({
    url: postUrl,
    type: "POST",
    data: { data_id : id, data_name1: data1, data_name2: data_name2 },
    dataType: "text",//サーバーから返ってきた内容のデータ方式(他にはhtml,jsonなど)
    success : function(response){
    //通信成功時 php側でechoした内容がresponseに入っている
    },
    error: function(){
        //通信失敗時の処理
        alert('通信失敗');
    }
});

送信した内容をコントローラで扱う時は次のように書きます
今回は'edit’メソッドに送ることにします。

<?php
public function edit($data_id, $data_1 $sata_1){
        $this->Model->id = $id;

        if ($this->request->is(['ajax'])) {
            if ($this->Model->save($this->request->data)) {
                echo "失敗です";
            } else {
                echo "失敗です";
            }
        }
    }
}
 

【CakePHP】セレクトボックスの作り方&注意点

フォームヘルパーを使ってセレクトボックスを作るときはズバリ、以下の通りに書けば出来ます。

echo $this->Form->input('field', array(
    'options' => array('りんご', 'みかん', 'バナナ'),
));

$this->Form->inputの第2引数の配列に'options'というキーを追加して、
配列を値にすればいいわけです。

 

ところがこの場合、実際にセレクトボックスの選択肢としては
「りんご」、「みかん」、「バナナ」が表示されるのですが
データベースに登録されるデータは順に「1」、「2」、「3」という数字になってしまいます。

つまり実際にデータベースに送信されるのは配列の値でなくキー(1から始まる?)が送信されているわけです。

 

なのでセレクトボックスの表示内容と送信されるデータを同じにしたいときは
キーを明示的に指定してやればOKです。
(もちろん意図的にキーと値をばらしてもOK)

echo $this->Form->input('field', array(
    'options' => array('りんご'=>'りんご', 'みかん'=>'みかん', 'バナナ'=>'バナナ'),
));

【CakePHP】MVCモデルとは何なのか

CakePHPMVCモデルという設計方式を採用しています。

この「MVC」とはそもそもなんなのか、ということでざっくり概要をまとめてみました。

 

今回のポイント

MVCとは何なのか

MVCのメリット

 

MVCとは何なのか

アプリケーションをモデル、ビュー、コントローラの3つに分ける設計方式です。
それぞれの役割はこんな感じです

  • モデル
    アプリケーション内部で行われる仕事を担当します。
    具体的にはデータをデータベースから取得したり、データベースに挿入されるデータを加工したり、検証したりします。
  • ビュー
    アプリケーションを使うユーザーが実際に目にするインターフェースや、
    入力フォームなどを担当します。
  • コントローラー
    モデルとビューの橋渡しを担当します。
    モデルの
    「データベースの内容を表示させたいから、
     表示担当のビューにこのデータを回してください」という依頼や、
    ビューの
    「ユーザーが入力した内容をデータベースに保存したいから、
     データベース管理担当のモデルに回してください」
    という依頼を引き受けます。

ざっくり言えば

モデルは内部の仕事、ビューが外部の仕事、コントローラは両者の橋渡し、といえます。

 

MVCのメリット

各機能が独立していて、お互いの依存性も最小限なのがMVCの特徴です。
そのため、

・各機能がソースコード上ではっきりと別れているため、分業しやすい
 名前の衝突とか無駄な肥大化を避けられます。 

・いずれかの機能に変更があっても、他の機能に与える影響が小さい

というメリットがあります。

 

【CakePHP jquery】その場編集(edit in place)を実装してみた

 

以前、その場編集をプラグインで実装するという記事を書きましたが
結局うまく動かすことが出来ませんでした(下記参照)

【CakePHP】その場編集(edit in place)をプラグインでやってみる - kento0824jp’s diary

 

色々と先輩にアドバイスを伺った所、自分で作るのもそんなに難しくなさそうだったので、やってみました。

たぶんちゃんと動いたはずなので、コードや注意点その他をまとめておきます。

 

さっそくですがソースコードです

$(function(){
    'use strict';

    var currrentTd;
    var selectedTd;
    var recordId;
    var columnName;
    var formId
    var currentText;
    var isFirstClick = true;
    $('#table td.record').dblclick(function(){
        if (!isFirstClick){// 一番最初にダブルクリックしたときはpostしない
            currentText = $('#' + formId).val()
            postToEdit(selectedTd, recordId, columnName, currentText);
        }

        // ダブルクリックした(選択した)セルと「編集中のセル」が同じならば
        // 何も選択していない状態に戻す
        currrentTd = '#' + $(this).attr('id');
        if(currrentTd == selectedTd){
            selectedTd = ''
            isFirstClick = true;
            return;
        }
        selectedTd = '#' + $(this).attr('id');
        recordId = $(this).attr('id').split('-')[0]
        columnName = $(this).attr('id').split('-')[1]

        formId = $(this).attr('id') + '_form'
        var form = "<textarea rows= '3' " + "id ='" + formId + "'>" + initialText + "</textarea>"
        $(selectedTd).html(form);
        isFirstClick = false;
    });


    function postToEdit(selectedTd, id, columnName, currentText){
        if(currentText.length == 0){// 空文字列を送信しないようにする
            content = '*EMPTY*'
        }
        var editUrl = '/my_app/items/edit/' + id + '/' + columnName + '/' + currentText
  // editはcontorollerのfunction edit

        $.ajax({
        url: editUrl,
        type: "POST",
        data: { id : id, columnName: columnName, content: currentText },
        dataType: "text",
        success : function(response){
            //通信成功時
            var textEdited = response.split('<!DOCTYPE html>')[0];
            if(textEdited == '*EMPTY*'){
                textEdited = '';
            }
            $(selectedTd).html(textEdited);
        },
        error: function(){
            //通信失敗時の処理
            alert('通信失敗');
        }
        });
    };
});

ざっくり概要

今回作ったのは「その場編集できるテーブル要素」です。

テーブルはデータベースの内容を表示するものです。

以前「ダブルクリックすると色が変わることで『今このセルを選択中です!』ということを示すテーブル」を作りました。

 【jquery】表のセルを選択可能にする - kento0824jp’s diary

これを応用して、

「セルAをダブルクリックすると選択状態にする」

「Aの中にテキストボックスを表示」

「セルBをダブルクリックするとAのテキストボックスの入力内容をPOST」

「Bを選択状態にして、Aの選択を解除する」

というものを作りました。

 

POSTはajaxを使ってコントローラのメソッドに飛ばしています。

細かい解説

$('#table td.record').dblclick(function(){
        if (!isFirstClick){// 一番最初にダブルクリックしたときはpostしない
            currentText = $('#' + formId).val()
            postToEdit(selectedTd, recordId, columnName, currentText);
        }

まだどのセルもダブルクリックしていない
=どのセルも選択していない
=何も編集していない
=POSTするものが何もない

なので、一番最初のダブルクリックでない場合のみPOSTします。

currrentTd = '#' + $(this).attr('id');
        if(currrentTd == selectedTd){
            selectedTd = ''
            isFirstClick = true;
            return;
        }

編集中のセルをもう一度ダブルクリックした場合は
内容をPOSTした上で、どのセルも選択していない状態に戻るようにしています。

 

selectedTd = '#' + $(this).attr('id');
recordId = $(this).attr('id').split('-')[0]
columnName = $(this).attr('id').split('-')[1]

こちらがPOSTするまえの諸々の準備です。
今回は各セルに #レコードid-カラム名 という形式のid属性を付けていますので、そこからレコードidとカラム名を取得します。

 

続きましてPOSTする関数です。
大体はajaxでPOSTするときの一般的な描き方通りだと思いますが、1点だけ解説しておきます。

if(currentText.length == 0){// 空文字列を送信しないようにする
    content = '*EMPTY*' }

CakePHPではコントローラのメソッドに与える引き数をアドレスの後ろにスラッシュ区切りで記述します。

このとき、スラッシュ区切りの中身が空だとメソッド上では未定義変数として扱われてしまうみたいです。

これを防ぐために、空文字列を*EMPTY*という文字列で一時的に置き換えるようにしています。

【chrome】500 Internal Server Errorの原因を調べるには?

非同期通信の処理など、ページの遷移がない処理がうまく動作しない時、
デベロッパーツールのconsoleに「500 Internal Server Error」が出ている場合があります。

 

こうしたとき、デベロッパーツールのnetworkタブを見ることで、エラー内容を確認することができます。

 

f:id:kento0824jp:20180107214831p:plain

 

ここで「status」列に500と表示されているものがあれば、
それがエラーの発生したサーバー側のプログラムです。

f:id:kento0824jp:20180107214942p:plain

該当のリソースを選択して、previewタグを見るとエラー内容が表示されています。