//グローバル変数の定義
var top_dif;           // マウスポインタと画像のY座標の差分
var left_dif;          // マスポインタと画像のX座標の差分
var outframe_pos;      // 画像表示窓領域の座標格納オブジェクト

var inframe;         // 画像格納領域のdiv要素
var outframe;        // 画像表示窓領域のdiv要素

var tile_width = 100;  // タイルの幅
var tile_height = 100; // タイルの高さ
var tile_rows    = 7;  // タイルの行数
var tile_columns = 32; // タイルの列数

var start_x = -1300;   // 最初に表示する画像位置のx座標
var start_y = -200;    // 最初に表示する画像位置のy座標

var loaded_tiles = new Array();  // 既読のタイル名を格納する配列
var outframe_width;    // 画像表示窓の幅
var outframe_height;   // 画像表示窓の高さ

// バブリングとデフォルトイベントアクションの停止
function stopDefaultAndPropagation(e) {
    // バブリング停止
    if(e.stopPropagation) {
        e.stopPropagation();
    }
    if(window.event) {
        window.event.cancelBubble = true;
    }
    // デフォルトイベントアクションを停止する
    if(e.preventDefault) {
        e.preventDefault();
    }
    if(window.event) {
        window.event.returnValue = false;
    }
}

// ドラッグ開始
function dragStart(e) {
    // 画像表示窓領域div要素の座標を取得
    outframe_pos = getElemPos(outframe);
    // 画像格納領域div要素の座標を取得
    var pos = getElemPos(inframe);
    // 画像格納領域div要素とマウスポインターの位置の差分を求める
    left_dif = e.clientX - pos.x;
    top_dif = e.clientY - pos.y;
    // ドキュメント全体にイベントリスナーをセット
    addListener(document, 'mousemove', moveElem, false);
    addListener(document, 'mouseup', dragEnd, false);
    // バブリングとデフォルトイベントアクションの停止
    stopDefaultAndPropagation(e);
    return false;
}

// ドラッグ終了
function dragEnd(e) {
    // イベントリスナー解除
    removeListener(document, 'mousemove', moveElem, false);
    removeListener(document, 'mouseup', dragEnd, false);
    // バブリングとデフォルトイベントアクションの停止
    stopDefaultAndPropagation(e);
    return false;
}

// ドラッグ中（子ウィンドウ移動）
function moveElem(e) {
    // マウスがブラウザー表示領域から外れたら終了
    if(
        (navigator.appName == 'Netscape' && navigator.userAgent.indexOf("Safari") < 0 ) ||
        navigator.userAgent.indexOf("Opera") >= 0
    ) {
        if(
            e.clientX >= window.innerWidth - 20 || e.clientX <= 10 ||
            e.clientY >= window.innerHeight - 30 || e.clientY <= 10
        ) {
            dragEnd(e);
            return false;
        }
    }
    // 画像格納領域div要素の移動
    var x = e.clientX - outframe_pos.x - left_dif;
    var y = e.clientY - outframe_pos.y - top_dif;
    inframe.style.left = x + 'px';
    inframe.style.top  = y  + 'px';
    // タイルに画像をロードする
    loadImage(x, y);
    pre_mouse_x = e.clientX;
    pre_mouse_y = e.clientY;
    // バブリングとデフォルトイベントアクションの停止
    stopDefaultAndPropagation(e);
    return false;
}

// タイルに画像をロードする
function loadImage(x, y) {
    // 表示窓に収まっているタイルの列番号の範囲を計算
    var columns_s = 0;
    if(x < 0) {
        columns_s =  Math.floor( Math.abs(x) / tile_width );
    }
    var columns_e =  Math.ceil( (outframe_width - x) / tile_width );
    if(columns_e > tile_columns - 1)  {
        columns_e = tile_columns - 1;
    }
    // 表示窓に収まっている行番号の範囲を計算
    var row_s = 0;
    if(y < 0) {
        row_s =  Math.floor( Math.abs(y) / tile_height );
    }
    var row_e =  Math.ceil( (outframe_height - y) / tile_height );
    if(row_e > tile_rows - 1)  {
        row_e = tile_rows - 1;
    }
    // 画像格納領域の座標を取得
    for(r = row_s; r <= row_e; r ++) {
        for(c = columns_s; c <= columns_e; c ++) {
            var tile_div_id = 'tile' + c + '_' + r;
            if(loaded_tiles[tile_div_id] == true) {
                continue;
            }
            // タイルdiv要素の参照
            var tile_div = document.getElementById(tile_div_id);
            // タイルdiv要素内にimgタグをセット
            var img = document.createElement('img');
            img.width = tile_width;
            img.height = tile_height;
            img.src = 'images/' + tile_div_id + '.jpg';
            tile_div.appendChild(img);
            // 既読のタイル名を格納する配列にtrueをセット
            loaded_tiles[tile_div_id] = true;
        }
    }
}

// 画像格納領域div要素内に、タイル状にdiv要素をセット
function initInframe() {
    var r;
    for(r = 0; r < tile_rows; r ++) {
        // 行div要素を新たに生成
        var row_div = document.createElement('div');
        // id属性値をセット
        row_div.id = 'row' + r;
        // サイズ（幅、高さ）をセット
        row_div.style.width = ( (tile_width + 2) * tile_columns ) + 'px';
        row_div.style.height = tile_height + 'px';
        // CSSのclearプロパティーを'both'にセット
        //row_div.style.clear = 'both';
        var c;
        for(c = 0; c < tile_columns; c ++) {
            // タイルに相当するdiv要素を新たに生成
            var tile_div = document.createElement('div');
            // id属性値をセット
            tile_div.id = 'tile' + c + '_' + r;
            // サイズ（幅、高さ）をセット
            tile_div.style.width = tile_width + 'px';
            tile_div.style.height = tile_height + 'px';
            // CSSのfloatプロパティーの値を'left'にセット
            tile_div.style.styleFloat = 'left';  // IE,Opera用
            tile_div.style.cssFloat = 'left'; // FireFox,Safari用
            /* デバッグ */
            // tile_div.style.color = '#ffffff';
            // tile_div.innerHTML = tile_div.id;
            // tile_div.style.border = '1px solid #ffffff';
            // タイルdiv要素を行div要素内に追加
            row_div.appendChild(tile_div);
        }
        // 行div要素をinframe内に追加
        inframe.appendChild(row_div);
    }
    // 画像表示窓領域div要素のサイズを取得
    outframe_width = outframe.offsetWidth;
    outframe_height = outframe.offsetHeight;
    // 画像格納領域div要素の位置をセット
    inframe.style.left = start_x + 'px';
    inframe.style.top  = start_y + 'px';
    // 画像を読み込む
    loadImage(start_x, start_y);
}

// 要素の位置を取得し、オブジェクトとして返す
function getElemPos(elem) {
    var obj = new Object();
    obj.x = elem.offsetLeft;
    obj.y = elem.offsetTop;
    while(elem.offsetParent) {
       elem = elem.offsetParent;
       obj.x += elem.offsetLeft;
       obj.y += elem.offsetTop;
    }
    return obj;
}

function getTargetNode(e) {
    // 対象要素の参照を取得
    var target_node;
    if(e.target) {
      target_node = e.target;
    } else {
      target_node = e.srcElement;
    }
    // Safari対策
    if (target_node.nodeType == 3) {
        target_node = target_node.parentNode;
    }
    return target_node;
}

// load時の処理
function setListeners(e) {
    // 画像表示窓領域と画像格納領域のdiv要素の参照をグローバル変数にセット
    outframe = document.getElementById('outframe');
    inframe = document.getElementById('inframe');
    // 画像格納領域div要素を初期化
    initInframe();
    // 画像表示窓領域div要素にmousedownイベントリスナーをセット
    addListener(outframe, 'mousedown', dragStart, false);
}

// イベントリスナー解除
function removeListener(elem, eventType, func, cap) {
    if(elem.removeEventListener) {
        elem.removeEventListener(eventType, func, cap);
    } else if(elem.detachEvent) {
        elem.detachEvent('on' + eventType, func);
    }
}

// イベントリスナー登録
function addListener(elem, eventType, func, cap) {
    if(elem.addEventListener) {
        elem.addEventListener(eventType, func, cap);
    } else if(elem.attachEvent) {
        elem.attachEvent('on' + eventType, func);
    } else {
        alert('ご利用のブラウザーはサポートされていません。');
        return false;
    }
}

// load時のイベントリスナーをセットする
addListener(window, 'load', setListeners, false);
