﻿// UTF-8
/**
 * scrollsmoothly.js
 * Copyright (c) 2008 KAZUMiX
 * http://d.hatena.ne.jp/KAZUMiX/
 * Licensed under the MIT License:
 * http://www.opensource.org/licenses/mit-license.php
 */


(function(){
    var SS_easing = 0.25;
    var SS_interval = 20;
    var SS_d = document;
    var SS_targetX = 0;
    var SS_targetY = 0;
    var SS_targetHash = '';
    var SS_scrolling = false;
    var SS_splitHref = location.href.split('#');
    var SS_currentHref_WOHash = SS_splitHref[0];
    var SS_incomingHash = SS_splitHref[1];
    var SS_prevX = null;
    var SS_prevY = null;

    // ドキュメント読み込み完了時にinit()を実行する
    ssF_addEvent(window, 'load', ssF_init);

    // ドキュメント読み込み完了時の処理
    function ssF_init(){
        // ページ内リンクにイベントを設定する
        ssF_setOnClickHandler();
        // 外部からページ内リンク付きで呼び出された場合
        if(SS_incomingHash){
            if(window.attachEvent && !window.opera){
                // IEの場合はちょっと待ってからスクロール
                setTimeout(function(){scrollTo(0,0);ssF_setScroll('#'+incomingHash);},50);
            }else{
                // IE以外はそのままGO
                scrollTo(0, 0);
                ssF_setScroll('#'+SS_incomingHash);
            }
        }
    }

    // イベントを追加する関数
    function ssF_addEvent(eventTarget, eventName, func){
        if(eventTarget.addEventListener){
            // モダンブラウザ
            eventTarget.addEventListener(eventName, func, false);
        }else if(window.attachEvent){
            // IE
            eventTarget.attachEvent('on'+eventName, function(){func.apply(eventTarget);});
        }
    }
    
    function ssF_setOnClickHandler(){
        var links = SS_d.links;
        for(var i=0; i<links.length; i++){
            // ページ内リンクならスクロールさせる
            var link = links[i];
            var splitLinkHref = link.href.split('#');
            if(SS_currentHref_WOHash == splitLinkHref[0] && SS_d.getElementById(splitLinkHref[1])){
                ssF_addEvent(link, 'click', ssF_startScroll);
            }
        }
    }

    function ssF_startScroll(event){
        // リンクのデフォルト動作を殺す
        if(event){ // モダンブラウザ
            event.preventDefault();
            //alert('modern');
        }else if(window.event){ // IE
            window.event.returnValue = false;
            //alert('ie');
        }
        // thisは呼び出し元になってる
        ssF_setScroll(this.hash);
    }

    function ssF_setScroll(hash){
        // ハッシュからターゲット要素の座標をゲットする
        var targetEle = SS_d.getElementById(hash.substr(1));
        if(!targetEle)return;
        // スクロール先座標をセットする
        var ele = targetEle
        var x = 0;
        var y = 0;
        while(ele){
            x += ele.offsetLeft;
            y += ele.offsetTop;
            ele = ele.offsetParent;
        }
        SS_targetX = x;
        SS_targetY = y;
        SS_targetHash = hash;
        // スクロール停止中ならスクロール開始
        if(!SS_scrolling){
            SS_scrolling = true;
            ssF_scroll();
        }
    }

    function ssF_scroll(){
        var currentX = SS_d.documentElement.scrollLeft||SS_d.body.scrollLeft;
        var currentY = SS_d.documentElement.scrollTop||SS_d.body.scrollTop;
        var vx = (SS_targetX - currentX) * SS_easing;
        var vy = (SS_targetY - currentY) * SS_easing;
        var nextX = currentX + vx;
        var nextY = currentY + vy;
        if((Math.abs(vx) < 1 && Math.abs(vy) < 1)
           || (SS_prevX === currentX && SS_prevY === currentY)){
            // 目標座標付近に到達していたら終了
            scrollTo(SS_targetX, SS_targetY);
            SS_scrolling = false;
            location.hash = SS_targetHash;
            SS_prevX = SS_prevY = null;
            return;
        }else{
            // 繰り返し
            scrollTo(parseInt(nextX), parseInt(nextY));
            SS_prevX = currentX;
            SS_prevY = currentY;
            var scope = this;
            setTimeout(function(){ssF_scroll.apply(scope)},SS_interval);
        }
    }

}());
