フロントエンドの業務でAJAXでバックエンドと接続して内容を取得してデータを表示する、なんていう場面は多々あると思います。
ただ、AJAXで取得したデータを一つ一つ要素を作成して流し込んでいく事が面倒だったり、表示の並びなどはViewだけでちょっと触るだけで変更できればバックエンドの処理が減って良かったりします。
今回は、jQueryとJavaScriptの便利ライブラリ集Lodashのテンプレート機能とソート機能を使ってみたいと思います。
WEBシステム開発等で気付いたことなどをまとめていきます。
フロントエンドの業務でAJAXでバックエンドと接続して内容を取得してデータを表示する、なんていう場面は多々あると思います。
ただ、AJAXで取得したデータを一つ一つ要素を作成して流し込んでいく事が面倒だったり、表示の並びなどはViewだけでちょっと触るだけで変更できればバックエンドの処理が減って良かったりします。
今回は、jQueryとJavaScriptの便利ライブラリ集Lodashのテンプレート機能とソート機能を使ってみたいと思います。
「ボタンを押したらXMLから値をajaxで取ってきてフォームに入れて、その値を即座に10倍した値を別のフォームに入れたい」
という設定でコードを書く。
この画像の条件で「読め」を押すと、まず50の入っているフォームが2000に上書きされて、その下の10倍に20000が入るはず。
…。これで数日かかりました。なぜ読み込む前の値を読んでしまうのか。
「successコールバックに書く」という方法もなくはない。なくはないが
実際は「読み込んだ値をすぐ別のajaxで送信して」的なことが発生していた。
訳が分からなくなる…。
調べてみると、jQuery.Deffred と .then() という書き方があることに気づく。
ざっくりいうと、
「processedとかrejectedが返されるまで待機」
「$.ajaxはこっそりprocessedとかrejectedを返している」
「$ajax().then()のthen節にふたつfunctionを入れることができて、前半はprocessedのあと、後半はrejectedのあと実行される」
「.then()を直結連鎖させると上からprocessed側が実行されていく」…
とりあえず、.thenだ。と。
ajaxで値が変わるのを待ってから値をフォームから読んで書き直している。
これがやりたかったことだった。
まだまだ、使い方には研究が要りそうだ。
var deferred = new $.Deferred()
からの
return deferred.resolve().promise()
で
processedの結果を返したりとかもあった。
簡単なコードで連鎖に成功すると気持ちが良い。今はその感動だけ伝えたい…。
PDFファイルアップロードの機能を作成する場合、公開フォルダでない場所にアップロードして、
そのPDFファイルをaタグで別タブに表示したい場合があります。
そこで、その場合のサンプルを記載します。
ファイル名やIPアドレスはご使用の環境にあわせてください。
main.php(表示したいファイルをフルパスでGETで渡す。)
download
表示したいフォルダのファイルをオープンしてPDFとして表示させるためのphpファイル
pdfdisp.php
以上です。試してみてください。
ボタンをクリックしたら隠しdivの中のフォームをコピーして、
通し番号を発行して表に追加する、みたいな処理をよく書きます。
通し番号の入る場所は仮にダミー文字列(今回はQQQQ)を置いておいて、ボタンが押されたときの処理でまとめて書き換える感じです
何度か書いているうちにdata-属性に行番号を持たせることで、:lastから現在の最大行番号を把握し、
次の行番号を探る、なんてことをやるようになりました。
隠しフィールドよりずいぶんすっきり見えます。attrで持たせると文字列で保存されるので、取得時に0を引いて数値に解釈しなおすことをお忘れなく。 …【1】
追加するときだけじゃなくて削除にも役立ちます。$(“tr[data-no=’行番号’]”,”#fueruTable”).remove() で行ごと削れます。
ところで、これはこれで面倒なことが一つあって、これを実際submitしたとき。
QQQQはダミーフィールドなので使わないはずだし、何よりdataに関してforeachとか回すなんてことになると邪魔。
サーバー側にunset($_POST[‘data’][‘QQQQ’])を噛ませて長いことやってました。
ある時、formの閉じタグ位置を間違えて、隠しフィールドをformの外に追いやってしまったんです。
それでsubmitしたらどうなったかというと
QQQQがいない。
これはこれで何か問題がある気もするけれど、ただテンプレートとして置いておきたいだけで、そもそもsubmitする気のないフィールドは
そもそもform内に置かなければよかった!
考えてみれば当たり前のことなのに、長いこと気づかなかったのでついブログに書き出してしまいました。
submitしないフォームはformタグの外、アウトオブ眼中!他の事例でも使えたら使うつもりでいます。
2000/01/08から2005/05/31まで就労
2006/01/08から2010/05/31まで就労
2011/01/08から現在も就労
の全就労日数を求める方法を紹介します。
データ構造サンプル
CREATE TABLE users (
id INT NOT NULL AUTO_INCREMENT,
name VARCHAR(40) NOT NULL ,
PRIMARY KEY (id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_general_ci AUTO_INCREMENT=1 ;
CREATE TABLE works (
id INT NOT NULL AUTO_INCREMENT,
user_id INT NOT NULL ,
start_date DATE NOT NULL ,
retire_date DATE NULL DEFAULT NULL,
PRIMARY KEY (id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_general_ci AUTO_INCREMENT=1 ;
データの情報としては、
users.id:1,users.name:奥進太郎
works.id:1,works.user_id:1,works.start_date:2000/01/08,works.retire_date:2005/05/31
works.id:1,works.user_id:1,works.start_date:2006/01/08,works.retire_date:2010/05/31
works.id:1,works.user_id:1,works.start_date:2011/01/08,works.retire_date:null
1回毎の就労日数を求めるVIEWを作成します。
CREATE VIEW work_diffs AS
select works.user_id AS user_id,
(case when isnull(works.retire_date) then (to_days(curdate()) – to_days(works.start_date))
else (to_days(works.retire_date) – to_days(works.start_date)) end end) AS work_diff
from `works`;
上記VIEWをgroup byで合計すると、全就労日数が取得できます。
CREATE VIEW work_sum_diffs as
select work_diffs.user_id as user_id,sum(work_diffs.work_diff) as sum_work_diff
from work_diffs group by work_diffs.user_id;
usersとwork_diffsをJOINすれば、users毎の全就労日数を取得することができます。
案件にて、色を扱いたいといった事があって、サクッと色を選べるプラグインが無いかなと探してみた所、spectrum.jsというイイ感じのプラグインが見つかりましたので、ご紹介したいと思います。
このプラグインはjQueryに依存しますので、jQueryを先に読み込ませます。
そして、使用したいhtmlにspectrum.jsとspectrum.cssを読み込みます。
jquery.spectrum-ja.jsは日本語対応です。必要である場合は使用します。
inputにクラス名を付けておきます。
bodyタグの最後にscriptにてspectrumを呼び出します。
パレットに予め色を用意しておきたい場合は、paletteプロパティに配列で色を#RRGGBB形式で入力しておきます。
jQuery(function($){ $(".picker").spectrum({ color: "#f00", //初期色 showPalette: true, // パレット表示あり palette: [ // パレットで使う色を指定 ["#f00", "#0f0", "#00f", "#ff0", "#f0f", "#0ff"] ] }); });
IE11を使用してシステムにsubmitした際、データが飛ばないので探ってみると、カラーピッカーを使用した後にinputのvalueに#RRGGBBの形で値が設定されていませんでした。
spectrumに用意されている`change`イベントでinputを#RRGGBB値に書き換えるようにしてやれば解決しました。
jQuery(function($){ $(".picker").spectrum({ color: "#CF85A1", //初期色 showPalette: true, // パレット表示あり palette: [ // パレットで使う色を指定 ["#CF85A1", "#CCD58D", "#94DAC0", "#A49CDF", "#ACA4E4"] ], change: function(color) { $(this).val(color.toHexString()); } }); });
簡単な設定で細かい色指定ができるので、これは重宝しそうです。
注:ブログ移転記事ではありません
4月後半となると、新生活に伴う引越もひと段落して、生活が軌道に乗った頃かと思います。
奥進システムでも、引越を進めています。
SVNからGitの引越で、事務所が物理的に動いているわけではないですけどね。
SVNからGitに乗り換えるにあたって、やることを調べていて、
最初こそおっかなびっくりやってたんですが、今となれば手順がはっきりしてきたので、
簡易版ではあるけれど、引越の為にやったことを今回のブログに書こうかと。
一応準備:
・Git Bashでプロジェクト展開先に入っておく
・他のGit操作がなんか面倒ならSourceTreeなど見繕っておく
1:Git Bash上、git-svnでSVNリポジトリをGitリポジトリに転換して抽出
git svn clone -s svn+ssh://[プロジェクトのアドレス]
SVNで使ってたtrunkが取り出される感じです。
もし最終リビジョンだけでいいなら -r HEAD をアドレスの前に付ければよし。
2:SVNに関する設定を抹消する
ここは色々と試していました。なんとかSVNと縁を切る方法はないかと。
SourceTreeから毎回「SVNブランチ作る?」と作れもしないのに聞かれるのにウンザリしていたものですから。
結局、2ステップにまとまりました。
プロジェクト直下.gitフォルダの中を操作するので、隠しフォルダの表示をお忘れなく
2-1:configファイルのsvn-remote “svn”以下項目を削除
このファイルに[svn-remote]で始まる項目があると思います。そこをテキストエディタで開いて消すだけです。
2-2:svnフォルダも丸ごと削除
もしかしたらもうちょっとうまいことやる方法あるのかもしれないですけれどね。
今のところ問題はないのでこちらもバッサリ削除。
3:ついでに.gitignoreとemptyファイルを用意しておく
.gitignoreは無視リスト、
毎回管理するかどうか聞くなとするファイルをリストしておけます。(詳しい書き方はご自分で。)
emptyファイル今こそファイルは入っていないけれど将来的にないと困るフォルダを抑えておくカカシみたいなもの。
gitはファイルのないフォルダを覚えていてくれませんからね…。
.gitignoreみたいにドット始まりのファイルをWindowsで作りたいなら、
ファイル名を”.gitignore.”とするといいみたいです。
もちろん、この変更は「Gitに」コミットしておきましょう。
5:あとは適当にリモートとつなげてプッシュ
まだローカルにGitリポジトリがある状態です。
チームで共有するために、リモートリポジトリを作ります。
とりあえずはこんなところです。
細かい設定をできる限り追うことなくSVNと縁を切る方法、
少なくとも、configファイル編集とsvnファイルの丸ごと削除だけは大事です。
phpExcelにて列を指定して値を表示する際に、
EXCEL列の配列になったものをインデックスで指定して表示できれば、
横に長い表を作成する際に役に立つと思いこのテーブルを作成しました。
// EXCELの横座標を設定する。 $col1 = array("","A","B","C","D","E","F","G","H","I","J","K","L","M","N","O","P","Q","R","S","T","U","V","W","X","Y","Z"); $col2 = array("","A","B","C","D","E","F","G","H","I","J","K","L","M","N","O","P","Q","R","S","T","U","V","W","X","Y","Z"); $col3 = array("A","B","C","D","E","F","G","H","I","J","K","L","M","N","O","P","Q","R","S","T","U","V","W","X","Y","Z"); $col4 = array("A","B","C","D","E","F","G","H","I","J","K","L","M","N","O","P","Q","R","S","T","U","V","W","X","Y","Z"); $colArr = array(); $idx = 0; foreach ($col1 as $val1) { if ($val1 == "") { foreach ($col2 as $val2) { foreach ($col3 as $val3) { $colArr[$idx] = $val1 . $val2 . $val3; $idx++; } } } else { foreach ($col4 as $val2) { foreach ($col3 as $val3) { $colArr[$idx] = $val1 . $val2 . $val3; $idx++; } } } } $col = 0; $row = 1; $sheet->setCellValue("{$colArr[$col]}{$row}", "日付"); // A1に「日付」表示 $col = 26; $sheet->setCellValue("{$colArr[$col]}{$row}", "日付"); // AA1に「日付」表示 $col = 702; $sheet->setCellValue("{$colArr[$col]}{$row}", "日付"); // AAA1に「日付」表示 $col = 1378; $sheet->setCellValue("{$colArr[$col]}{$row}", "日付"); // BAA1に「日付」表示 $col = 16383; $sheet->setCellValue("{$colArr[$col]}{$row}", "日付"); // XFD1に「日付」表示 ここがEXCEL横の最大値です。
PHPEXCELにて、列表記をインデックスで扱いたい時の配列です。
案件で全画面ページを簡単に作るプラグイン「fullpage.js」を使用する事がありました。
今回、レスポンシブ対応にあたって、文章等が1ページの範囲を超える場合があり、その際はスクロールバーを表示してスクロールできるようにしたいため、scrolloverflow.js
も使用しました。
そちらの簡単な使い方とハマった所をtipsとして取り上げます。
まずは、必要な読み込みファイルから。
まず、表示させたいページに必要なCSSとjsを読み込みます。
全画面ページにしたい所は起点の要素(今回はIDがfullpageの要素)と、その子クラスにsection
の名前を付けます。
横スライドも欲しい場合は、section
要素にその子のクラスにslide
という名前を付けます。
Some sectionSome sectionSome sectionSome section
jQueryを使って呼び出します。
$('#fullpage').fullpage({ anchors: ['page1', 'page2', 'page3', 'page4'], // ページのアンカー名を指定 menu: '#global-menu', // グローバルメニューのID名 scrollOverflow: true, //全画面よりコンテンツが多い場合スクロールバーを出すかどうか loopHorizontal:false, //横スライダーをループさせない touchSensitivity: 16, //タッチデバイスでのセクション切替の強さの閾値 afterLoad: function (anchorLink, index) { //セクションが読み込み終わりのイベント if (index === 1) { //TOPロード時 }else if(index === $('#fullpage .section').length){ //最下ページ時 }else{ //その他のページの時 } }, afterSlideLoad: function (anchorLink, index, slideAnchor, slideIndex) { // スライドが読み込み終わった後のイベント }, onLeave: function (index, nextIndex, direction) { // セクションを離れた時のイベント }, onSlideLeave: function (anchorLink, index, slideIndex, direction, nextSlideIndex) { // スライドを離れた時のイベント }, afterResize: function () { // リサイズ後のイベント } });
グローバルメニューが要る場合には、上記menu:"#global-menu"
のように指定して、li要素のdata-menuanchor
に上記anchors
配列で指定した名前と対応させます。
そうすると、グルーバルメニューのクラスに現在居るページはactive
が付きます。ページが遷移される度に現在居るクラスにactive
が付き、移動元ページのactive
クラスは外れますので、メニューのON/OFFのCSSの装飾などが簡単に作れます。
これで、縦4ページ、3ページ目に横に4スライドある全画面ページが出来上がったと思います。
作成に当たって色々とありましたので、そこで得たTipsをドドーンと紹介しちゃいます。
全画面のページのサイズが確定した後にAJAXやdisplay:none
していた要素を表示させて、表示させている要素が増えた場合、スクロールする領域が足りない事が起きたりします。その際は、rebuild()
関数を呼び出して、再度サイズ計算し新たなページのサイズを確定させます。
// フェードイン・フェードアウトの後fullpage.js再計算 $("#recruit-space").fadeToggle(500,function(){ $.fn.fullpage.reBuild(); })
jQueryのロード時とfullpage.jsのロード時はタイミングとして別になるので、 fullpage.jsが読み込まれた後に処理を走らせたい場合は、afterRender
以下に処理を書きます。
afterRender: function () { //(例)クリッカブルマップレスポンシブ $('img[usemap]').rwdImageMaps(); }
fullpage.jsは1ページを複数ページとして見せているだけなので、普通にGoogle Analyticsコードを貼っても該当ページの読み込み時に1回しか送られません。
貼るコードを分けて、縦ページの遷移、横ページをスライドさせた時に、Analyticsのコードを送るように書けば思うようなデータが取れます。
通常のアナリティクスコード読み込みの時に、下の方にあるga('send', 'pageview');
を外します。
そして、fullpage.jsの横スライドが読み込まれた際に起きるイベントafterSlideLoad
内にga('send'...
のコードを書きます。
afterSlideLoad: function(anchorLink, index, slideAnchor, slideIndex) { ga('send', 'pageview', { 'page': anchorLink, 'title': slideAnchor }); },
縦ページ遷移に対応するにはadterLoad
イベント内に記述します。
afterLoad: function (anchorLink, index) { ga('send', 'pageview', { 'page': anchorLink, 'title':anchorLink }); }
SPA風にページが手軽に作れたり、アイデア次第で面白いページが作れると思います。その分独自のライフサイクルやイベントがあるのでハマり所があったり、SEO的にはどうなるんだろうと思う所がありましたが、ここまで対応できれば普通に使えそうですね。
また何かあったら追記しようと思います。
今回ファイルを選択してあげている所をドラッグアンドドロップでファイルを指定して上げたいという要望を受けて対応しました。
jqueryさえあれば簡単に出来ちゃうので一番シンプルなサンプルを作ってみました。
続きを読む ドラッグアンドドロップでファイルをアップロードする