カテゴリー: jQuery

jQuery UIでリストのソート機能を実装したときにFirefoxとかでinputのフォーカスがおかしくなる件

AngularJsのディレクティブでリストのソート機能を
実装していて困ったのでメモ。

ディレクティブでは実際には「jQuery UI」の「sortable」を
利用していた。

各々のバージョンは以下
jQuery v2.1.3
jQuery UI v1.11.4
AngularJS v1.3.15

実装したコードは以下。

app.directive('mySortable',function(){
    return {
        link:function(scope,el,attrs){
            el.sortable({
                revert: true,
                axis: 'y',
                cancel: "",
                handle: ".sortable-handle"
            });
            
            el.disableSelection().delegate('input,textarea','click',function(ev){
                ev.target.focus();
            });
            
            el.on( "sortdeactivate", function( event, ui ) {
                //ソートした時の挙動
                ・・・
            });
            
        }
    }
})

上記の状態だと「Firefox」と「IE」でソートは出来るのだけどソートする対象内に
あるinputタグにフォーカスが当たるけど全選択(Ctrl+a)とかができないし、
入力値がある場合にもなぜか必ず入力エリアの左側にカーソルが入ってしまう
現象が発生した。

結局以下↓の箇所を

el.disableSelection().delegate('input,textarea','click',function(ev){
    ev.target.focus();
});

【jQuery】sortable()を設定したタグ内のtextarea, inputタグに入力出来ない」このページの内容通りに以下↓のように変更。

el.bind('click.sortable mousedown.sortable',function(ev){
    ev.target.focus();
});

直った。。

jQuery UI の.disableSelection()がdeprecated(非推奨)になってる件

↑これとかの影響なのかな・・・。

■参考URL

【jQuery】sortable()を設定したタグ内のtextarea, inputタグに入力出来ない

Ticket #4429 (closed bug: notabug) Can’t select text in inputs within sortables

jQuery UI の.disableSelection()がdeprecated(非推奨)になってる件

fullcalendar.jsで予定が重なったときの表示順番を指定する

fullcalendar.jsで予定が重なったときの表示順番を指定する

すごく優秀なfullcalendar.js

元々の「fullcalendar.js」では予定が重なった場合に
タイトルを比較してどちらを左に出すのか決めているみたい。

これだと予定に色をつけた場合にタイトルで左右が
決まってしまうから同じ色の予定でも左右バラバラに
表示されて美しくない。

ということでfullcalendar.jsを変更。

function compareSlotSegs(seg1, seg2) {
    return seg1.start - seg2.start || // earlier start time goes first
        (seg2.end - seg2.start) - (seg1.end - seg1.start) || // tie? longer-duration goes first
        (seg1.event.title || '').localeCompare(seg2.event.title); // tie? alphabetically by title
}

もともと週表示では↑のようになっているので

function compareSlotSegs(seg1, seg2) {
    return seg1.start - seg2.start || // earlier start time goes first
        (seg2.end - seg2.start) - (seg1.end - seg1.start) || // tie? longer-duration goes first
        (seg1.event.color || '').localeCompare(seg2.event.color) ||
        (seg1.event.title || '').localeCompare(seg2.event.title); // tie? alphabetically by title
}

↑このように変更。
タイトルで比較する前にcolorプロパティで比較するのを追加。
登録順とかも気にする場合はidとかで比較するのもいいかも。

// A cmp function for determining which segments should appear higher up
function compareDaySegments(a, b) {
    return (b.rightCol - b.leftCol) - (a.rightCol - a.leftCol) || // put wider events first
        b.event.allDay - a.event.allDay || // if tie, put all-day events first (booleans cast to 0/1)
        a.event.start - b.event.start || // if a tie, sort by event start date
        (a.event.title || '').localeCompare(b.event.title) // if a tie, sort by event title
}

↑月表示側も

// A cmp function for determining which segments should appear higher up
function compareDaySegments(a, b) {
    return (b.rightCol - b.leftCol) - (a.rightCol - a.leftCol) || // put wider events first
        b.event.allDay - a.event.allDay || // if tie, put all-day events first (booleans cast to 0/1)
        a.event.start - b.event.start || // if a tie, sort by event start date
        (a.event.color || '').localeCompare(b.event.color) ||
        (a.event.title || '').localeCompare(b.event.title) // if a tie, sort by event title
}

↑同じ感じで修正

■参考URL

jQuery fullcalendar integration with PHP and MySQL

FullCalendarの日本語化やオプションいろいろ

FullCalendarの導入からカレンダー毎の色指定まで

HTML5のwindow.postMessage()でクロスドメインでのiframe内から 親のwindowにメッセージを送る方法

HTML5のwindow.postMessage()でクロスドメインでのiframe内から
親のwindowにメッセージを送る方法。

クロスドメインのページをiframeで読み込んだときに
iframe内のページ(長いページ)が遷移したら親ページもページの
上部に移動するようにしたくて調査した。

■参考サイト
window.postMessage

window.postMessage() を使って、クロスドメインの iframe の高さを設定する検証

window.postMessage()の学習

上記のサイトを参考にして以下のようなコードを作成

■親ページ側に追加したjsのサンプル

$('#next_click').live('click', function(){
     var target = parent.postMessage ? parent : (parent.document.postMessage ? parent.document : undefined);
     if (typeof target != "undefined"){
         target.postMessage("page change", "*");
     }
});

上記でid:next_clickがクリックされたら親に「page chage」というメッセージが送られる。
※jQuery使用

■子ページ側に追加したjsのサンプル

$(function(){
        $(window).on("message", function(e){
        if (e.originalEvent.origin == 'http://許可するドメイン') {
            var data=e.originalEvent.data;
            if(data==='page change'){
                $('html,body').animate({scrollTop:0}, 400);
            }
        }
    });
})

上記で子でメッセージを受けとった際にページを上部まで移動させられる。
※jQuery使用
最初にあげた参考サイトではaddEventListenerを使っていたけど↑はjQueryで
イベントをセットしている。
jQueryを使う場合は「e.origin」や「e.data」でデータが取得できないので
「e.originalEvent.origin」や「e.originalEvent.data」でデータを取得する。
※eをconsole.dirすればわかる。

jQueryと一緒にRequireJSを使ってみる

jQueryと一緒にRequireJSを使ってみる

RequireJSをちゃんと使うべく勉強。
WEB+DB PRESS vol.69に
「RequireJSでらくらくモジュール管理」
というのがあったのでこれを参考にする。

まずはRequireJSのメリット3つ
□カプセル化されたモジュールの定義
AMD(Asynchronous Module Definition)モジュールと呼ばれるカプセル化された再利用性の高いモジュール定義が行える。
AMDはコールバック関数を使って定義するのでグローバル変数に頼らずに他のモジュールを呼び出せる

□ネストした依存関係の自動解決
依存関係が多段にネストしていても利用するモジュールを呼べば自動でRequireJSが依存を解決してくれる。

□非同期読み込みと最適化ツールによるパフォーマンスの向上
非同期に読み込むことでレンダリングのブロックを回避できる。
最適化ツールが用意されている(今回の実験ではやらない)

ではとりあえず書いてみる。
元々記事に記載されていたコードをjQueryを使った
バージョンに書き換えてみる。

RequireJSはここのページの「Sample RequireJS 2.1.2 + jQuery 1.8.2 project」をおとしてくる
※2012/12/07時点です。
ここから先のサンプルコードで使っている「require-jquery.js」は
解凍したフォルダの中の
jquery-require-sample\webapp\scripts\require-jquery.js
を使っています。

■ファイルの構成

.
|– js
| |– component.js
| |– config.js
| |– counter.js
| |– maxheight.js
| |– page.js
| |– require-jquery.js
| |– require.js
| `– util.js
`– page.html

require.jsとrequire-jquery.jsの両方があるけど
jquery使う場合はrequire-jquery.jsがいいらしい。
ただrequire-jquery.jsはrequire.jsとjquery.jsを
連結しただけのものらしい。
でもこうすることでjqueryのプラグインが非同期で
ロードされる前に本体がロードされていることを保障
できるってことらしい。

■page.html

<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8">
    </head>
    <body>
        <!-- 現在の時刻を表示する -->
        <h1 id="label"></h1>
        <div id="clock"></div>
        <hr /><!-- 単純なjqueryプラグインの実験↓ -->
        <label>一番大きいdivの高さ</label>
        <p id="height"></p>
        <hr /><!-- 複数のライブラリ中でjqueryプラグンが呼び出されたときの実験↓ -->
        <label>呼び出された回数</label>
        <p id="count"></p>
        <script>
            var require = {
                // キャッシュの防止
                urlArgs: 'bust=' + (new Date()).getTime()
            };
        </script>
        <script src="js/require-jquery.js" data-main="js/page" async></script>
    </body>
</html>

■js/config.js

define(function() {
    return {
        label: '現在の時刻',
        format: '%Y/%m/%d %H:%M:%S'
    };
})

■js/util.js

define(function() {
    function pad2(num){
        return ('0' + num).slice(-2);
    }

    function formatDate(date, formatStr) {
        return formatStr.
            replace('%Y', date.getFullYear()).
            replace('%m', pad2(date.getMonth() + 1)).
            replace('%d', pad2(date.getDate())).
            replace('%H', pad2(date.getHours())).
            replace('%M', pad2(date.getMinutes())).
            replace('%S', pad2(date.getSeconds()));
    }

    return {
        formatDate: formatDate
    };
});

■js/component.js

define(['jquery', 'config', 'util', 'counter'], function($, config, util) {
    function display($elem){
        $elem.text(util.formatDate(new Date(), config.format));
    }

    function render($elem) {
        display($elem);
        setInterval(function() {
                $(this).counter();
                display($elem);
            }, 1000);
    }

    return {
        render: render
    };
});

■js/page.js

require(['jquery', 'config', 'component', 'maxheight', 'counter'], function($, config, clock) {
    // configのラベルを表示(config依存)
    $('#label').text(config.label);

    // 現在の時刻を表示(component依存)
    clock.render($('#clock'));

    // ここから下はおまけの実験
    // ページ内のdiv要素で最も高いもののheightを返してみる(maxheight依存)
    $('#height').text($('div').maxHeight());

    // 5秒に1回たまったカウントを表示(counter依存)
    setInterval(function() {
        $('#count').countDisplay();
    }, 5000);
});

■js/maxheight.js

define(['jquery'], function($) {
    $.fn.maxHeight=function(){
        var max = 0;
        this.each(function() {
            max = Math.max( max, $(this).height() );
        });
        return max;
    };
});

■js/counter.js

define(['jquery'], function($) {
    var count=0;
    $.fn.counter=function(){
        count++;
    };
    $.fn.countDisplay=function(){
        this.text(count);
    }

});

■実際にうごかした画面。。。

実際に書いてみると以外に簡単に使えるんだなという印象。
自作したライブラリはとりあえずdefineで囲めばいいっぽいし。
defineで囲みたくない場合はshim設定で利用すれば擬似的に
モジュールで使えるということらしい。

後は今回でいうpage.jsの中でKAYACのURL dispatcher的な
ものを使えばよりいい感じになるのかもしれない。

そこそこ規模が大きくても何とかなるjavascriptの設計(URL dispatcherの薦め)

■参考URL

JavaScriptを分割&非同期で読み込めるRequireJS

RequireJS 2.0による依存関係の明示、フォールバック、複数バージョンの混在

勉強会資料シェア Getting Started with RequireJS

java-ja.js #2 RequireJS実践編

jQueryのプラグインをつくってみよう

jQuery 郵便番号から住所を表示するPostal Search Ajax API

以前prototype.jsとかを使って郵便番号から住所を検索して表示する
ライブラリを使っていた事があったけどjQueryでもそういったものがないのか
調べてみたらあった。

Postal Search Ajax API チュートリアル

ここが素晴らしい。

郵便番号と住所のデータベースは Postal Search APIs & Solutions のサーバで管理するため、あなたの WEB サーバに データを格納したり、最新データを維持する必要はありません。

但し利用に当たってはPostal Search APIs & Solutions 利用規約をちゃんと守りましょう。

非常識なアクセスしないようにしないとね。

使い方は簡単で「郵便番号から住所を検索する #1」みればわかると思う。

因みに以前利用させてもらっていたライブラリはこちら。

AjaxZip2

こちらもjQueryにも対応されていたみたいです。

あっajaxzip3っていうのもあったんだ・・・。気付かなかった。。

jQuery getでキャッシュされなようにする

jQueryでgetメソッドを利用した際にIEでキャッシュされてしまい内容が更新されなかったのでメモ。

$.ajaxSetup() メソッドでキャッシュしないように指定します

$.ajaxSetup({
	cache: false
});
$("#target_ajax_load").load("hello.html");

jQuery.ajax(settings)
IEにてAjax通信がキャッシュされる、F5でリフレッシュしてもダメ

jQuery サンプルメモ

jQueryの実際のサンプルコードがある分かりやすいサイトをメモしておく。

少しのコードで実装可能な20のjQuery小技集(webクリエーターボックス)

プラグイン無しでjQueryだけの小技が紹介されています。なによりサイトが綺麗だし見やすい。

Index of Semooh jQuery Sample Site(jquery sample)

74のサンプルが紹介されています。こちらはプラグインを利用しているものも含みます。
実際にその場で動作を確かめられる上に設定値を変更したりできる。

JavaScript + Ajax + jQuery 実践サンプル集

とにかく沢山のサンプルがある。。

jQueryってサンプル見てるだけでなんか楽しい。

さて今日は深夜作業なんでこれくらいで。。(ネタが無いだけ)

jQuery IEでattrが動かなくて困った。

前のエントリでdefaultValueのことを書いたけどIEで動かなかった・・・。

とりあえず試したのはIE8

HTML部分はこんな感じ

<input type="hidden" value="" name="back_id" id="back_design_no" />

以前書いたIEで動かない例

var selected_id = 'hogehoge';
$("#back_design_no").attr("defaultValue", selected_id);

こう書いたら動いた

var selected_id = 'hogehoge';
$("#back_design_no").attr({"value": selected_id});

他にもIEで動かない書き方があることを知った。。。

参考
jQuery が IE でうごかねぇーーー、って思ったので、メモっとく。

console.logで動かないとか言ったことあるなーw

jQuery live関数 サポートしていないイベント

jQueryのlive関数で指定できるイベントを勘違いしていたのでメモ。

live(type, fn)

jQuery 1.3より実装。
イベントに対してハンドラを登録します。
登録されたイベントは、現在および将来的にも、セレクタにマッチする全ての要素に適用されます。
カスタムイベントに対してbindすることも可能です。

この関数で指定できるイベントは以下

  • click
  • dblclick
  • mousedown
  • mouseup
  • mousemove
  • mouseover
  • mouseout
  • keydown
  • keypress
  • keyup

もっと読む jQuery live関数 サポートしていないイベント