﻿/* ***************************************
* 
*       hamu.js
* 
* 更新
* 2010.06.02 hamu.days 実装
* 2010.06.01 hamu.ajax 実装
* 
****************************************** */
/*
    1. hamu モジュール
    2. その他
*/




// hamu モジュール 始まり
var hamu = window.hamu = {};

// ブラウザチェックとIE用cssセット
hamu.checkBrowser = {
    IE : !!(window.attachEvent && navigator.userAgent.indexOf("Opera") === -1),
    setIEhaslayout : function(elm){ // IEのhaslayoutプロパティを有効にするため zoom:1 を適用
        elm.style.zoom = 1;
    }
};

// クラスを取得
hamu.getElementsClass = function (target, parentElement) {
    var expression;
    if (target) {
        expression = '//*[contains(concat(" ",@class," "), " ' + target + ' ")]'
        parentElement = parentElement || document;
        return hamu.AfroXPath(expression, parentElement);
    }
    return false;
};
// class属性の追加・削除
hamu.classChange = {
    add : function(elm, classNameString){
        // class属性に classNameString がなければ追加
        if(!hamu.classChange.has(elm, classNameString)){
            elm.className += (elm.className ? " " : "") + classNameString;
        }
    },
    remove : function(elm, classNameString){
        var attrs;
        var myArray;
        // クラス属性から classNameString を削除
        attrs = elm.className; // 変数 attrs にclass属性を代入
        attrs = attrs.replace(classNameString, ""); // classNameString を削除
        myArray = attrs.split(/\s+/); // 半角スペースで区切られた文字列を配列で変数 myArray に代入
        attrs = myArray.join(" "); // 配列を半角スペースで結合
        elm.className = attrs; // 文字列をclass属性に代入
    },
    has : function(elm, classNameString){
        // elm の class属性に classNameString があるかどうか調べる
        if(elm){    // 念のため elm が存在しているかどうか
            var attrs = elm.className.toString().split(/\s+/);  // elm の class の属性値を文字列に変換して、空白の区切りで分割して配列にする。
            for(var i = 0; i < attrs.length; i += 1){
                if(attrs[i] == classNameString){    // もし classNameString があったら true を返す。
                    return true;
                }
            }
        }
        return false;   // それ以外は false を返す。
    }
};

// イベント周りを定義
hamu.event = {
    addListener : function(elm, type, func){
        if(elm.addEventListener){
            elm.addEventListener(type, func, false);
            return true;
        }else if(elm.attachEvent){
            var r =elm.attachEvent("on" + type, func);
            return r;
        }else{
            elm["on" + type] = func;
        }
    },
    removeListener : function(elm, type, func){
        if(elm.removeEventListener){
            elm.removeEventListener(type, func, false);
        }else if(elm.detachEvent){
            elm.detachEvent("on" + type, func);
        }
    },
    stopDefaultEvent : function(event){
        event = event || window.event;
        
        // イベントによる default 動作（ページ遷移）を無効化
        if(event.preventDefault){
            event.preventDefault();
        }else{
            event.returnValue = false;
        }
        
        // 必要であれば、イベント浮上も止める
        if(event.stopPropagation){
            event.stopPropagation();
        }else{
            event.cancelBubble = true;
        }
    }
    
};

// Array from XPath "AfroXPath" を定義
hamu.AfroXPath = function(expression, parentElement){
    var toArray = [];
    var fromXPath = document.evaluate(expression, parentElement || document , null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE ,null);
    for (var i = 0; i < fromXPath.snapshotLength; i += 1) {
        toArray.push(fromXPath.snapshotItem(i));
    }
    return toArray;
}

/* チェック関数群 */
// 配列かどうか確かめる関数
hamu.is_array = function (value) {
    return value &&
        typeof value === 'object' &&
        typeof value.length === 'number' &&
        typeof value.splice === 'function' &&
        !(value.propertyIsEnumerable('length'));
};
// 数字かどうか確かめる関数
hamu.is_number = function (value) {
    return typeof value === 'number' && isFinite(value);
}



// フェードさせるエフェクト hamu.effect 開始
hamu.effect = {
    fadeIn: function repeatFadeIn(elm, speed, alpha){ // setTimeoutで段階的に透明度を変化
        if(alpha === 10){
            hamu.effect.setOpacity(elm, alpha);
        }else if(alpha < 10){
            alpha += 1;
            hamu.effect.setOpacity(elm, alpha);
            setTimeout(function(){repeatFadeIn(elm, speed, alpha)},speed);
        }
    },
    fadeOut: function repeatFadeIn(elm, speed, alpha){ // setTimeoutで段階的に透明度を変化
        if(alpha === 0){
           hamu.effect.setOpacity(elm, alpha);
        }else if(alpha > 0){
            alpha -= 1;
            hamu.effect.setOpacity(elm, alpha);
            setTimeout(function(){repeatFadeIn(elm, speed, alpha)},speed);
        }
    },
    
    setOpacity: function(elm, alpha){ // 透明度をセット
        elm.style.opacity = alpha/10;
        elm.style.MozOpacity = alpha/10;
        elm.style.filter = 'alpha(opacity=' + alpha*10 + ')';
    }
}; // フェードさせるエフェクト hamu.effect 終了


// Ajax関連
hamu.ajax = function (sourceFile, callBack) {
    var createHttpRequest, getData;
    
    createHttpRequest = function(){
        var req = window.XMLHttpRequest ? new XMLHttpRequest() :
        (function(){
            try { return new ActiveXObject("Msxml2.XMLHTTP"); }
            catch(e) {
                try { return new ActiveXObject("Microsoft.XMLHTTP"); }
                catch(e) { return null; }
            }
        })();
        return req;
    };
    
    getData = function(sourceURL, callBackFn){
        var req = createHttpRequest();

        req.onreadystatechange = function(){
            if (req.readyState == 4) {
                callBackFn(req);
            }
        }
        req.open('GET', sourceURL, true);
        req.send(null);
    };
    
    getData(sourceFile, callBack);
};


// 英語の曜日・月を日本語に変換する hamu.days を定義
hamu.days = {
    /**
     * 英語の曜日を日本語に変換
     * hamu.days.days_of_week(str, style_num);
     * str <= 英語の曜日(ex. "Monday")
     * style_num <= 0 : "月"
     *              1 : "月曜"
     *              2 : "月曜日"
     */
    days_of_week : function (str, style_num) {
        var style = [
            [
                "月",
                "火",
                "水",
                "木",
                "金",
                "土",
                "日"
            ],
            [
                "月曜",
                "火曜",
                "水曜",
                "木曜",
                "金曜",
                "土曜",
                "日曜"
            ],
            [
                "月曜日",
                "火曜日",
                "水曜日",
                "木曜日",
                "金曜日",
                "土曜日",
                "日曜日"
            ]
        ];
        
        style_num = style_num || 0;
        
        str = (str.toLowerCase()).slice(0, 3);
        
        switch (str) {
            case "mon" :
                return style[style_num][0];
            case "tue" :
                return style[style_num][1];
            case "wed" :
                return style[style_num][2];
            case "thu" :
                return style[style_num][3];
            case "fri" :
                return style[style_num][4];
            case "sat" :
                return style[style_num][5];
            case "sun" :
                return style[style_num][6];
            default :
                return "no days of the week";
        }
    },
    
    /**
     * 英語の月を数字・日本語に変換
     * hamu.days.month(str, style_num);
     * str <= 英語の月(ex. "April")
     * style_num <= 0 : "4"
     *              1 : "四"
     *              2 : "卯月"
     */
    month : function (str, style_num) {
        var style = [
            [
                "1",
                "2",
                "3",
                "4",
                "5",
                "6",
                "7",
                "8",
                "9",
                "10",
                "11",
                "12"
            ],
            [
                "一",
                "二",
                "三",
                "四",
                "五",
                "六",
                "七",
                "八",
                "九",
                "十",
                "十一",
                "十二"
            ],
            [
                "睦月",
                "如月",
                "弥生",
                "卯月",
                "皐月",
                "水無月",
                "文月",
                "葉月",
                "長月",
                "神無月",
                "霜月",
                "師走"
            ]
        ];
        
        style_num = style_num || 0;
        
        str = (str.toLowerCase()).slice(0, 3);
        
        switch (str) {
            case "jan" :
                return style[style_num][0];
            case "feb" :
                return style[style_num][1];
            case "mar" :
                return style[style_num][2];
            case "apr" :
                return style[style_num][3];
            case "may" :
                return style[style_num][4];
            case "jun" :
                return style[style_num][5];
            case "jul" :
                return style[style_num][6];
            case "aug" :
                return style[style_num][7];
            case "sep" :
                return style[style_num][8];
            case "oct" :
                return style[style_num][9];
            case "nov" :
                return style[style_num][10];
            case "dec" :
                return style[style_num][11];
            default :
                return "no month";
        }
    },
    
    // (未完成) 時差修正する lag_correction を定義
    lag_correction : function (setting) {
        var year,month,date,day,next_day,hour,minute,country,
            lag_time,lag_hour,lag_minute;
        var result = {};
        var days_of_week = ["mon","tue","wed","thu","fri","sat","sun"];
        var country = {
            "japan" : "+0900"
        };
        var end_of_month = [31,28,31,30,31,30,31,31,30,31,30,31];
        var check_leap_year = function (num) {
            if ((num%4 === 0) && (num%100 !== 0) ||
                (num%4 === 0) && (num%400 === 0)) {
                    return true;
            } else {
                return false;
            }
        };
        var add_zero = function (str) {
            if (str.length === 1) {
                return str = "0" + str;
            } else {
                return str;
            }
        };
        
        // 設定代入
        year = parseInt(setting.year, 10) || 0;
        if (!hamu.is_number(setting.month)) {
            month = parseInt(this.month(setting.month, 0), 10);
        } else {
            month = parseInt(setting.month, 10) || 1;
        }
        date = parseInt(setting.date, 10) || 1;
        day = (setting.day).toLowerCase().slice(0, 3) || "";
        hour = parseInt(setting.hour, 10) || 0;
        minute = parseInt(setting.minute, 10) || 0;
        // country と lag_time が同時に設定されている場合 lag_time を優先
        lag_time = setting.lag_time ? setting.lag_time : (country[setting.country].toLowerCase());
        if (!lag_time) {return false;}
        lag_hour = parseInt(lag_time.slice(1,3), 10);
        lag_minute = parseInt(lag_time.slice(3,5), 10);
        
        if (lag_time.charAt(0) === "+") {   // 時差がプラスの時
            minute = minute + lag_minute;
            hour = hour + lag_hour;
            if (minute > 60) {
                minute = minute - 60;
                hour += 1;
            }
            if (hour > 24) {
                hour = hour - 24;
                for (var i = 0; i < days_of_week.length; i += 1) {
                    if (day === days_of_week[i]) {
                        if ((i + 1) >= days_of_week.length) {
                            next_day = days_of_week[0];
                        } else {
                            next_day = days_of_week[i + 1];
                        }
                    }
                }
                day = next_day;
                date += 1;
            }
            // 閏年でかつ２月ならば
            if (check_leap_year(year) && month === 2) {
                if (date > (end_of_month[month - 1] + 1)) {
                    date = date - (end_of_month[month - 1] + 1);
                    month += 1;
                }
            } else { // 閏年の２月でない場合
                if (date > end_of_month[month - 1]) {
                    date = date - end_of_month[month - 1];
                    month += 1;
                }
            }
            if (month > 12) {
                month = month - 12;
                year += 1;
            }
            
        } else if (lag_time.charAt(0) === "-") {    // 時差がマイナスの時
            minute = minute - lag_minute;
            hour = hour - lag_hour;
            if (minute < 0) {
                minute = 60 + minute;
                hour -= 1;
            }
            if (hour < 0) {
                hour = 24 + hour;
                for (var i = 0; i < days_of_week.length; i += 1) {
                    if (day === days_of_week[i]) {
                        if ((i - 1) < 0) {
                            next_day = days_of_week[days_of_week.length - 1];
                        } else {
                            next_day = days_of_week[i - 1];
                        }
                    }
                }
                day = next_day;
                date -= 1;
            }
            // 閏年でかつ３月（前の月が２月になる）ならば
            if (check_leap_year(year) && month === 3) {
                if (date <= 0) {
                    date = (end_of_month[month - 2] + 1) + date;
                    month -= 1;
                }
            } else { // 閏年の３月でない場合
                if (date <= 0) {
                    if (month === 1) {
                        date = end_of_month[11] + date;
                    } else {
                        date = end_of_month[month - 2] + date;
                    }
                    month -= 1;
                }
            }
            if (month <= 0) {
                month = 12 + month;
                year -= 1;
            }
            if (year <= 0) {
                year -= 1;
            }
            
        }
        
        result["year"] = year.toString();
        result["month"] = month.toString();
        result["date"] = date.toString();
        result["day"] = day;
        result["hour"] = add_zero(hour.toString());
        result["minute"] = add_zero(minute.toString());
        
        return result;
    }
};

// hamu モジュール 終わり



// その他関数

if (typeof Object.create !== 'function') {
    Object.create = function (o) {
        var F = function () {};
        F.prototype = o;
        return new F();
    };
}

if (typeof Function.prototype.method !== 'function') {
    Function.prototype.method = function (name, func) {
        if (!this.prototype[name]) {
            this.prototype[name] = func;
            return this;
        }
    };
}

