first_time_user_or_not

特定ページへの初回訪問かどうかを見分ける

jQueryなどを使って初回訪問時のみアクションを加えたい。でもクッキーなんて使いたくない。

…という場合には、ウインドウ名を利用して簡易的に判断する方法が有効です。javascriptで表示中のURLからファイル名(ベースのスラッグ)を取得し、ウインドウ名に加える処理を行います。

verify first time visitor or not

<script type="text/javascript">

    //verify first time visitor or not in the pages
    var $currentpath = window.location.pathname.replace(///, '').replace(/./, '').replace(/_/, '-'); // 表示中のページのファイル名を取得する
    if ( !$currentpath ) $currentpath = "homepage"; // トップページ(ファイル名が存在しない場合)に登録する任意のファイル名
    if ( window.name.indexOf( '#' + $currentpath )!=-1 ) { //ウィンドウ名に現在のファイル名が含まれるかチェック
        alert( "I've seen you before!" ); // リロードや2度目以降の訪問時の処理
    } else { 
        window.name = window.name + '#' + $currentpath; // ウィンドウ名の末尾にファイル名を追加する、#はエスケープ処理
        alert( "It's nice to see you!" ); // 初回訪問時の処理
    }

</script>

チェックしたいページ全てに記述する必要があります。ウインドウ名を利用しているので別窓で開くと無効になります。

なお、ウインドウ名には文字数制限(255文字かな?)があるはずなので、動的サイトで全体のアクセス履歴を書き込んでいくのは無理があります。また、ウィンドウ名に指定できるのは半角英数字のみです。なのでwordpressなどのCMSに埋め込むなら、トップページや固定ページ内だけなどに絞って、何かアクションさせたいときに使いましょう。wordpressなどのCMSで埋め込むなら、ページテンプレートやホームテンプレート内で使用し、らpathnameを取得する手続きをカットし、直接phpでpost IDを使った名前を代入する方が、処理も早くて文字数も抑えられます。以下はWPで実際に私が使ってる感じに近いもの。

var currentid = <?php echo "'p$post->ID#'"; ?>; // #はエスケープ処理
if ( window.name.indexOf( currentid ) == -1 ) { // 初アクセス 
    window.name = window.name + currentid; // ウィンドウ名の末尾にファイル名を追加する
    //以下処理が続く
}

 

そもそもユーザーがホームページへの初回訪問かどうかを判別する場合

おまけ。

ニュースなどのウインドウをポップアップしたいときなど、すべてのページでユーザーが初回訪問かどうか有効にしたいときもあります。この場合、チェックしたい各ページ全てに記述する必要があります。

<script type="text/javascript">

    //verify first time visitor or not in the site
    var $my_window = "my_homepage"; // 任意のウィンドウ名を指定
    if ( window.name.indexOf( $my_window )!=-1 ) { //任意のウインドウ名かチェック
        alert( "I've seen you before!" ); // 2度目以降の訪問時の処理
    } else { 
        window.name = $my_window; // ウィンドウ名を任意に名付ける
        alert( "It's nice to see you!" ); // 初回訪問時の処理
    }

</script>

とにかく外部からのアクセス時の一回だけでいい、という場合は以下のようにシンプルに処理する方法もあります。リファラを見ているので、別ウインドウで開いても大丈夫ですし、該当するページ一箇所に記述するだけで済みます。しかしスクリプトの設置の有無で判別できないので、サブディレクトリ以下でのみチェックをしたい場合には不向きです。

<script type="text/javascript">

    //verify first time visitor or not in the site
    
    if( document.referrer.indexOf( "//example.com" )!=-1 ) {  { //リファラにアドレスが含まれているか。
        alert( "I've seen you before!" ); // 2度目以降の訪問時の処理
    } else { 
        alert( "It's nice to see you!" ); // 初回訪問時の処理
    }

</script>
imagelightbox-js

//osvaldas.info/image-lightbox-responsive-touch-friendly

 

軽くてシンプルでカスタマイズしやすいレスポンシブでタッチフレンドリーなライトボックス

ほとんどタイトルで言い切ってしまったのだけども、Image LightboxはデフォルトではCSSは何も指定されていないというシンプルなライトボックス系のjQueryプラグイン。エフェクト開始、画像読み込み、読み込み終了、エフェクト終了、等々コールバックが充実しているので、ウェブデザインや用途に合わせてとてもカスタマイズしやすい作りになっている。ライトボックスが珍しかった時代はともかく、ユーザーがウェブ体験に慣れている現在、余計なUIがない方が扱いやすいのではないかと思う。

簡単な設定

使い方は簡単でまずはjsを読み込みます。

<script src="jquery.js"></script>
<script src="imagelightbox.js"></script>
<script>
    jQuery( function($){
        $( 'a' ).imageLightbox();
    });
</script>

次にcssに以下を設定

#imagelightbox{
    position: fixed; z-index: 9999;
    -ms-touch-action: none; touch-action: none;
}

以上です。

が、しかし…

Image Lightboxはie8に対応していないという、ブラウザ島国事情にとってあまりに厳しい条件。なんとかして使いたいと思ったので、以下ではie8対応にする方法を考えることにします。(作者のValutisさんはリトアニアの方のようだけども、レガシーブラウザは死滅しているみたい…めちゃめちゃうらやましい。)

 

ImageLightbox.jsをIE8対応に変更する

やってみたら主な(すべてではない)障害は二つあった。

parseIntで整数値が返ってこない

一つはparseIntの対象となる要素(デフォルトだとimg#imagelightbox)のcssでleftの値がエラーを起こすことで、cssに値を与えれば良いのだが、それだけでは中央揃えも出来ない有様なのでcssハックで中央揃えすることに。

img#imagelightbox { position:fixed; z-index:9999; -ms-touch-action:none; touch-action:none; } /* minimal css */
img#imagelightbox { left:09; right:09; top:09; bottom:09; margin:auto9; } /* IE8 hack */

load functionが発火しない

これで本体に手を付けずに済んだ…と思ったのもつかの間、いったん機嫌良く表示された画像を閉じ、再度リンクを押して表示しようとすると画像が読み込まれないという。これはあれだ。たいへん残念なIEらしい、画像がキャッシュされてしまうとload functionが発火しないという致命的なバグ。139行下のload function手前のjQueryでsrcを付与している処理、これをfunctionから切り離して後述するように変更。

元のコード

image = $( '<img ' + options.selector + ' />' )
.attr( 'src', target.attr( 'href' ) )
.load( function()
{
image.appendTo( 'body' );
setImage();
/////////// 略 ///////////
})
.error( function()
{if( options.onLoadEnd !== false ) options.onLoadEnd();
})

これを次のように変更してやります。

image = $( '<img ' + options.selector + ' />' ).appendTo( 'body' );
image.load( function()
{
setImage();
/////////// 略 ///////////
})
.error( function()
{if( options.onLoadEnd !== false ) options.onLoadEnd();
});
image.attr( 'src', target.attr( 'href' ) );

改変したコードはここにあげときます。(コードを改変したくなければ、ie8の場合のみリンク末尾にjsでタイムスタンプを付ける、という手法でも回避できるのではないかと思います。未検証ですが。)

sc 2014-10-08 12.54.38開設してからこっち、このブログではコードの表示にWP SyntaxHighlighterを使っていました。このプラグイン、見た目はシンプルで満足していたんですが、使わない機能が多くてボリュームがあるし、いろいろなコードも吐き出す。で、長いこと更新されていないな、というわけでこのたび変更することにしました。
いくつかのHighlighter系のプラグインをテストしてみるも、どれも私には高機能すぎ…。で、この機にプラグインをやめてhighlight.jsを導入することにしました。ウェブデザインに関してはまさに、過ぎたるは及ばざるが如し、ですからね。


このhighlight.jsの一番気に入ったところは、コードの種類を自動判定してくれるので特別なマークアップが不要ということ。つまり、<pre>と<code>で括ってあげればそれでよいから、データの持ち回しに優れている。導入方法は色々あると思いますが、私はテーマ内に上げて、wp_headに読み込ませています。

    wp_enqueue_script('highlight', get_bloginfo('template_directory').'/js/highlight.js');
    wp_enqueue_style('highlight', get_bloginfo('template_directory').'/js/好きなテーマ.css');
    wp_head();
    echo '<script>hljs.initHighlightingOnLoad();</script>'."n";

すでにwordpressのプラグインを使っている場合、preタグだけでマークアップされていることも多い。その場合は以下のようにjQueryなどでイニシャライズしてあげればよい。

$(document).ready(function() {
  $('pre').each(function(i, block) {
    hljs.highlightBlock(block);
  });
});

……と、公式の説明通りに設定でいったん上手くいったと思ったのですが、jsが効いていない記事が!どうやら長文のコードだと自動判別が効かないことがあるらしい。その場合は、そのコードのマークアップを直書きすればよい(<pre><code class=”php”>みたいな感じ)のだけども、今度は、同ページ内の他のpreタグすべてにJSが効かなくなってしまい…。結局テーマのphp内でcodeタグの有無をチェックして挿入することにしました。ま、その方がデザインもしやすいということで、結果OKですかね。

//preタグにcodeタグを挿入する

function insert_precode( $comment_content ) {
    preg_match_all('/<pre.*?>([^`]*?)</pre>/is', $comment_content, $matches, PREG_SET_ORDER); 
    foreach ($matches as $def_pre) {
        $pre = $def_pre[0];
        if ( !preg_match('/<pre.*?>+s*<code.*?>([^`]*?)</code>+s*</pre>/is', $pre) ) { //CODEタグがなければ挿入
            $pre = preg_replace('/<pre(.*?)>([^`]*?)</pre>/is', '<pre$1><code>$2</code></pre>', $pre);
            $comment_content = str_replace( $def_pre[0], $pre, $comment_content );
        }
    }
    return $comment_content;
}
add_filter( 'comment_text', 'insert_precode', 9);
add_filter( 'the_content', 'insert_precode' );