メン醤のjQuery workshop

jQueryの小技などのサンプルをコード例として紹介するブログです。ネイティブJavaScriptから移行したいjQuery初心者向け、jQueryの魅力を知ってもらえたら。

テキストボックスを最大文字数まで入力したら次のフィールドへフォーカスする入力補助

固定長テキストボックスとでも言いましょうか。。

郵便番号・クレジットカード・シリアルナンバーのような
複数あるフィールドの各桁数が固定で決まっているテキストボックスが複数並んでいる場合に、
文字列長の最大桁数まで入力したら次のテキストボックスへ自動でカーソルを移したい
などの要件がたまにあったりします。

つまり、郵便番号でいえば、最初の3桁・次の4桁、とテキストボックスが分かれていて
3文字入力したら次の4桁のテキストボックスにフォーカスをする。
とでも言いましょうか。
(以降text1, text2と呼びますね)

でもそれって、考えなければいけないことが少しあったりします。
色々なキーの入力制御です。

挙動

  • 3桁入力してtext2にてバックスペースを押したらカーソルはtext1に移る。
    さらにtext1の1文字を削除することもできるような処理とする。
  • 左右の矢印キーにてテキストボックス内を移動している場合
    text1text2内は端に来た場合でも前後に移動できるようにしたい。

他にも要件によって出てくるものもあるかも知れません。
今回はこれを実装してみました。

動作 (デモ)

テキストボックスのグループには3つ以上あってももちろん正常に作動します。


jQuery fixed input group

実装

HTML側はこんな感じです。

classにfixed-input-groupというものを勝手に定義して宛てています。
Bootstrapではinput-groupがありますが、これを踏襲して命名しています。 これによりハンドリング対象のテキストボックスのグループを特定させます。

また、<input type="text" maxlength="20"> のようにmaxlengthの指定を行います。
これにより、最大文字列長まで入力された場合に次input要素へフォーカスなどの動作を実現させます。

jQuery側は
$('.fixed-input-group').on('keydown', 'input', function(e) {
と実装して.fixed-input-group内のすべてのinputタグへの入力を処理していきます。

function内は、大きく分けて2つのブロックから成っています。
前半は特殊キー押下時の挙動。
後半はABCなど通常キー押下時の挙動です。

  • Backspaceキー押下の場合で、入力要素が既に空の場合は、前のinput要素へfocusします。
  • 左矢印キー押下の場合で、カーソルが先頭にある場合は、前のinput要素へfocusします。
  • 右矢印キー押下の場合で、カーソルが最後にある場合は、次のinput要素へfocusします。

後半部は

  • 入力が最大文字列長まで行われていたら、次のinput要素へfocusします。
    focusしたinputもmaxlengthまで入力されているかどうかで、少し挙動を変えています。
    (ここらへんは好みと決めの問題ですね。)

ちなみに

郵便番号のハイフン区切りから連想して、
電話番号も同じように実装できそうと思うかも知れませんが、
携帯電話の番号は区切り位置が固定ではないのでもう少し工夫が必要です。
text1が 090/080/050 だったら text2, text3 は4桁4桁ですが
text1が 042 とかだったら text2, text3 は3桁4桁になったり などとなるため、一筋縄ではいかなそうです。

jQuery.ajaxでWebスクレイピングを実装してみた

Webスクレイピングとは

Web上にある情報を取得して何かしらの形にまとめるスクリプト類です。
PHPなどサーバーサイドで定期実行してDBに格納するなどが
よくある使われ方だと思われます。

Webスクレイピングをする上でのマナー

アクセス後の処理は$.ajaxで非同期ですが
低頻度となるよう、間隔を1秒間空くように実装します。

Webスクレイピングの注意事項一覧 - Qiita

事例

qiita.com

美登利寿司という寿司店は行列が凄いが、Web上で待ち時間が見れるため
それをスクレイピングで観測して、なるべく並ばない時間帯に行きましょうという話。

渋谷のマークシティーにあるアレですね。
スクレイピングバンザイ!

jQuery

Webブラウザ上でロードしたところで、×ボタンをおしたら消えてしまうわけですが。
それでもちょっと集計したい、なんてこともあると思います。

概要説明というか方針というか

  • スクレイピング対象のWebページは一覧ページがあり、そこから個別ページ(子ページ)へのリンクがある
  • まず一覧が書いてあるページを取得
  • 一覧ページより個別ページのurlを抽出し、個別ページの情報を収集

シンプルですね。

表示については、空の<table>タグに取得結果を追記していく方式で
まずは取得した一覧情報から
<tr><td id="row3">個別ページurl</td></tr>
を追加し、その後
<tr><td id="row3">個別ページurl</td><td>個別の情報</td></tr>
となるよう<td></td>列を追加します。

実装 (wait用のfunction)

まずは遅延アクセス用のwait()functionを用意します。

jQueryへのwaitfunctionの拡張を行っています。
setTimeoutで指定時間後にresolveされるような仕組みになっているため
呼び出す側は

$.wait( 【遅延時間】 ).done(function() {
  // 非同期で遅延実行したい処理をここに書く.
});

と呼び出すことができるようになります。

実装 (取得処理)

次にメインとなる、一覧ページ取得からの個別ページ取得です。

ボタンクリック時、まず$.ajax()で一覧を取得しにいきます。
取得後のdoneでは

  • 取得した一覧より、各個別ページへのurl取得
  • 個別ページへidを採番します
    (個別ページのアクセスも非同期で行われているため、一意なidの採番が必要)
  • 列を追加して
  • 行*1000[msec]後に取得処理のgetDetailが実行されるようセットします

getDetail(detailUrl, rowid)は指定された個別ページurlをロードし
取得した情報をrowid行へ追加します。

動かしてみた

非同期で取得され、一覧取得後のアクセスが1秒置きに行われており
結果の取得順が違っても追加される行が正しいことが確認できます。


Webスクレイピングで乃木坂46メンバーのデータを取得

後記

ソース全文を見た方は大きなコメントアウトブロックを見て判ると思うのですが
個別ページのgetDetailがもう少し洗練できそうです。
具体的には、getDetailがwaitを共通処理として持つような形が良いかと考えています。

というのも、現在は遅延させる単位が1000msec*取得したい行番号となっており
この処理の中でその他に同じような処理があった場合や
特に、このボタンを2度押した時などは1秒ごとに二重に取得処理が走ることになり
それこそDDoSと変わらないなと。

つまり遅延実行処理そのものをスタックして1秒づつ処理していくような形がベストかなと。

そうなるとコールバック地獄にならないよう一工夫するか
結局グローバル変数になるのか。。
ちょっと正解は出ていないのですが、一旦この状態が正常かつある程度動くので
現在の状態を一つの解として掲載するに至りました。

相談にのってくれて、また、サンプルコードまで提供してくれたスーパー後輩に感謝ですm( )m

複数行のテキストボックスでいわゆる縦移動をする方法

色々言い方ありますが。

やりたいこと

テーブル/リストのような複数行表示の
その行の中にあるテキストボックスにおいて
上下キーを押したらカーソル(focus)が上下に移る

とでも言ったら正確でしょうか。。

jQueryでの実装

キーイベントが発生した要素のname属性を取得して
同じnameを保持する要素群を $('input[name="'+targetName+'"]'); で取得します。
そして、自分が何番目なのか、また、押されたキーが上なのか下なのかで
どの要素にフォーカスを移すか決定します。

HTMLの実装はこんな感じの前提です

まぁ、示すまでもないんですが。
上下キーで移動できる要素は同じnameが付与されていることが前提です。

jQuery 2.2.1 と 1.12.1 が出ました

ちょっと日が経ってしまいましたが、2016/2/22 にjQuery 1.12.1 と 2.2.1 がリリースされました。
今回は3.0へ向けてのパッチという位置付けのようです。

内容は、バグ修正と安定性向上で
特にIEでの position() メソッド挙動が改善されています。

1.x系はIE 6/7/8サポートで
2.x系はサポートされていない所は相変わらずですね。

blog.jquery.com

ところでイマドキIE8なんて使ってる人居るの?

jQueryでajax通信を利用するコード

下記のGit引用ソースの通りなのですが、大枠は

$.ajax({
    type: 'GET',
    dataType: '【取得するデータ型】',
    url: '【ajaxで取得するURL】'
}).done(function(data) {
    // 取得成功時の処理. 変数dataに値が入っている.
}).fail(function(data) {
    // 取得失敗時の処理.
});

こんな感じです。

上げているソースはGoogle画像検索APIを呼んで、その検索結果を表示しています。
詳細はGitHubに飛んで全体を確認してみてください。