たぼさんの部屋

いちょぼとのんびり

ver3.6

main.js

/**ver 3.6 3/13
 *
 * サイドメニューを固定した内容でセットするように変更する必要があります。(サブメニューがないコンテンツに対応するため)
 * SUBMENU_JSONを追記しました。
 * Page.prototype.createAndAppendSideMenuを追記しました。このメソッドで、サブメニューを生成してsubContainerにappendします。
 * 不要になったプログラムはコメントアウトしました。(firstTimeProcessのサイドメニュー生成部分)
 * また、サブメニューのスタイルを設定するために固定CSSファイルを作成します。
 * ファイル名はsubMenu.css
 *
 * デバイスの方向を変えた際、サブメニューが複数生成されるバグあり。
 *
 * スワイプ対応を追記しました。
 * バグあり。
 *  スライドメニュー開閉、スワイプとmenuAnchorの混合操作時に動作しなくなる。
 *  ver3.6 向きを変えるとサイドメニューが複数追加されるバグあり
 *
 * サイドメニューの位置を固定するためにnewContainer.cssに追記しました。
 * position:fixed ---表示のズレがandroid標準で見られるので削除しました。
 *
 * !!!operaminiならプログラムを停止します。動作不安定のため。Main.prototype.initilizeに追記しました。
 *
 * 【未実装部分】
 * ローディングアニメーション(スクロール時にアニメーションの動作が止まるのを解決必要)
 * サイドメニューのデザイン化
 * 戻るボタンの実装
 * ナビゲーションリンク(現在のページを表示)
 * !!他ドメインへのリンクにはAjaxリンクをセットしないように修正必要です。
 */
/*「過去の修正履歴」
 *
 * ver 3.5 3/12
 * 本番に合わせてBASEPATH = document.baseURI;に変更しました。
 * subContainerへside-naviコンテンツを追記しました。
 *
 * mainContainerへfooterコンテンツを追記しました。
 * これに伴って、ContainerクラスにsectionContainer , footerContainerを追加しました。
 * メインコンテンツの配置はsectionContainerに行うよう変更します。(ver3.4まではmainContainerでした)
 *
 *
 * firstTimeProcessでの動的高さの設定が意図通りに動作していません。
 * --setHeightToContainersメソッドをDOMContantLoaded時点で実行することで解決しました。
 * ver 3.4
 * Page.prorotype.removeDefaultCssDisableを追加して既存のcssを無効にするようにしました。
 * これに伴い、CLASS_NAMEを追記しています。初期値="EFOLABclass"です。
 * ページごとに新しいcssファイルを適用できるようにしました。
 * Page.prototype.setNewCssToChagePage(url)を追記しました。
 * PAGE_CSS_JSONを追記しました。
 * 遷移ページのコンテンツをセットするところで、androidブラウザの動作がappendでは動かないため
 * innerHTMLを使用していたところをouterHTMLでセットするよう変更しました。これで、id=maincolの部分も残りますので
 * スタイルセットのときに違和感がありません。
 * ----
 * firstTimeProcessではmaincolが存在するが、secondTimeProcessではその下位だけ存在するため
 * cssがセットしにく問題を修正
 * setContentsTosectionContainer:新規コンテンツをセットする部分を修正しました。
 *
 *
 * opera-miniでも動作はしています。(動作が遅いです)
 * ver 3.3
 *sectionContainer内部のアンカー要素にも、リンク生成部を記述しました。 : 動作ok
 *
 * --------------------------------------------
 * ver 3.2
 * 3/10(月曜)から修正
 * 修正項目
 * 1)android標準ブラウザ touchstartイベントによるページ遷移部分が default動作してしまうときあり。
 * ・window.stop()はコメントアウトしてある。
 * ・サブコンテンツにだけ、リンク設定するよう変更してみる
 * ・リンク生成部については修正完了しました。
 */
( function() {"use strict";
        /**
         * テスト用フラグです。
         * 試験としてpcサイトでも動作させるときはtrueをセットしておきます。
         */
        var TESTFLAG = true;
        var EVENT_NAME = 'touchstart';
        // var EVENT_NAME = 'click';

        /**
         * このプログラムを設置しているディレクトリです。
         * テストでのディレクトリ名を変更する際は同時に
         * 変更する必要があります。(変更しないとページごとのCSSが反映されません)
         * Page.prototype.setNewCssToChangedPageで使用しています。
         * "/"の記述は不要です。
         */
        var PROGRAM_Directory = "EFOLAB_ver3_6";
        /**
         * このプログラムで使用する新規要素(例えばcssのクラス名です)
         * Page.prototype.removeDefaultCssDisableメソッドでremove除外対象として使用しています。
         * スマホ用のCSSファイルは、HTMLファイルに追記するときには、必ずこのクラス名を記述する必要があります。
         */
        var CLASS_NAME = "EFOLABclass";
        /**
         * クラスの名前定義です。
         */
        var Page, Container, Device, Main;
        /**
         * ページのurlと適用すべきcssファイルを記述しているjsonファイルです。
         * ページごとのcssを切り替える際にしようします。
         * setNewCssToChagePageで使用します。
         */
        var PAGE_CSS_JSON = {
            "" : "top.css",
            "index.html" : "top.css",
            "guide/service.html" : "guide_service.css"
        };
        /**
         * サブメニューを生成するためのjsonArrayリストです。
         */
        var SUBMENU_JSON = [{
            "text" : "TOP",
            "href" : "index.html",
            "id" : "EFOLAB_submenu_top"
        }, {
            "text" : "活動の流れ",
            "href" : "guide/service.html",
            "id" : "EFOLAB_submenu_guide_service"
        }, {
            "text" : "料金プラン",
            "href" : "guide/price.html",
            "id" : "EFOLAB_submenu_guide_service"
        }, {
            "text" : "婚活パーティー",
            "href" : "party/index.html",
            "id" : "EFOLAB_submenu_party_index"
        }, {
            "text" : "魅力アップセミナー",
            "href" : "seminar/index.html",
            "id" : "EFOLAB_submenu_seminar_index"
        }, {
            "text" : "よくあるご質問",
            "href" : "question/index.html",
            "id" : "EFOLAB_submenu_question_index"
        }, {
            "text" : "ヴィーノの特徴",
            "href" : "about/index.html",
            "id" : "EFOLAB_submenu_about_index"
        }, {
            "text" : "独身vs結婚",
            "href" : "advise/index.html",
            "id" : "EFOLAB_submenu_advise_index"
        }, {
            "text" : "結婚でプラスなこと",
            "href" : "advise/plus.html",
            "id" : "EFOLAB_submenu_advise_plus"
        }, {
            "text" : "幸せな家族とは",
            "href" : "advise/family.html",
            "id" : "EFOLAB_submenu_advise_family"
        }, {
            "text" : "人生は戦略!",
            "href" : "advise/image.html",
            "id" : "EFOLAB_submenu_advise_image"
        }, {
            "text" : "成婚カップルの声",
            "href" : "voice/index.html",
            "id" : "EFOLAB_submenu_voice_index"
        }, {
            /**
             * ↓このcompany/access.htmlコンテンツにはid:maincolが存在しないようです。
             */
            "text" : "大阪サロンのご案内[アクセス]",
            "href" : "company/access.html",
            "id" : "EFOLAB_submenu_company_access"
        }, {
            /**
             * ↓このkyoto/index.htmlコンテンツにファイルが存在しません。(連絡あり)
             */
            "text" : "京都サロンのご案内",
            "href" : "/kyoto/index.html",
            "id" : "EFOLAB_submenu_kyoto_index"
        }, {
            /**
             * ↓このceo-intaview/index.htmlコンテンツにはid:maincolが存在しないようです。
             */
            "text" : "社長インタビュー",
            "href" : "ceo-intaview/index.html",
            "id" : "EFOLAB_submenu_kyoto_index"
        }, {
            "text" : "ヴィーノの求人情報",
            "href" : "recruit/index.html",
            "id" : "EFOLAB_submenu_recruit_index"
        }, {
            "text" : "",
            "href" : "",
            "id" : ""
        }];
        //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
        /**
         * ページを管理するクラスです。
         * @param {Decvice} device アクセスしているデバイスを取得したDeviceクラスのインスタンスです。
         * @constructor
         */
        Page = function(device) {
            /**
             * アクセスかウンターです。ページ遷移の際に+1増加させます。
             * @type {Number}
             */
            this.accessCounter = 0;
            /**
             * deviceです。
             * @type {Device}
             */
            this.device = device;
            /**
             * コンテナです。コンテンツを入れるレイアウトです。
             * @type {Container}
             */
            this.container = {};
            /**
             * コンテンツです。初回アクセス時は既存のhtmlDocを格納します。
             * 以降の遷移ページではAjaxでコンテンツを取得して格納します。
             * @type {Contents}
             */
            this.contents = {};
            /**
             * URLです。初回アクセス時に、取得しておきます。
             * 遷移イベントの発生時には、現在のurlと遷移先のurlを比較して同じならば、Ajax読み込みを実行しません。
             * @type String
             */
            this.url = window.location.href;
            /**
             * 各ページの動的スタイルシートをセットするための
             * link要素です。
             * 初期化してhead部にappendしておきます。
             * setNewCssToChangedPageメソッドで使用します。
             */
            this.cssLink = "";

            //-----------------------------------------------------------------------------------------------
            //Pageプログラム実行
            //-----------------------------------------------------------------------------------------------
            /**
             * 初期化を実行します。
             */
            this.initialize(this.url);
        };
        Page.prototype = {
            initialize : function(newUrl) {
                /**
                 * Pageインスタンスを指すselfです。
                 */
                var self = this;
                /*
                * load イベントは文書のローディング工程の終了時に発生します。
                * このイベントが発生した時点で、文書中の全てのオブジェクトは DOM 内にあり、
                * 全ての画像とサブフレームのロードは完了しています。
                *
                *readystatechangeではアンドロイド標準ブラウザで発火しません。
                * document.addEventListener('readystatechange', this, false);
                * window.onLoadならandroid標準ブラウザも発火します。
                */
                /**
                 * コンテンツの高さを動的に設定します。
                 * DOMContentLoadedの時点で意図通り動作します。
                 * (window.onloadはfirstTimeProcessでは、途中でwindow.stop()を実行しているため
                 * 動作しません。)
                 * [!!]document.addEventListenerでは動作しません。
                 */
                window.addEventListener('DOMContentLoaded', function(event) {
                    self.setHeightToContainers(self);
                }, false);
                /**
                 * 既存のCSSを無効にします。
                 */
                document.addEventListener('DOMContentLoaded', self.removeDefaultCssDisable, false);

                /**
                 * 初回ページか、遷移ページかを判定して
                 * プログラムを分岐します。
                 * this.accessCounter {Number} default:0
                 * 0なら初回アクセス
                 * 1なら2回目以降のアクセスと判断します。
                 * 初回アクセス時に+ 1増加させます。
                 */
                if (this.accessCounter === 0) {
                    /**
                     * 初回アクセスです。
                     * firstTimeProcessを実行します。
                     * 実行後にaccessCounterを+1します。
                     */
                    this.firstTimeProcess();
                    this.accessCounter += 1;
                } else {
                    /**
                     * 遷移ページです。
                     * 遷移先のurlが現在のurlと同じ場合(同一ページ)なにもしません。
                     * newUrl {String} 遷移先のurlです。
                     * this.url {String} 現在のurlを格納しています。
                     */
                    if (newUrl === this.url) {
                        return;
                    }
                    this.secondTimeProcess(newUrl);
                    /**
                     * 現在のページurlを表すthis.urlを遷移先のurlに更新します。
                     */
                    this.url = newUrl;
                }
            },
            /**
             * firstTimeProcess
             * 新規アクセスの時に実行します。
             * ---------------------------headload時---------------------------------
             * 1)新規コンテナを生成します。
             * 新規コンテナのmenuAnchorにイベントを設定します。
             * -------------------------DomContentLoad時-----------------------
             * 2)新規コンテナを配置します。
             * 既存コンテンツをfragmentに移動します。
             * 既存コンテンツの読み込みを中止します。:window.stop();
             * --------------------------window.onload時--------------------------
             * 動的スタイル(コンテンツの高さ)を設定します。
             */
            firstTimeProcess : function() {
                /**
                 * Pageを指すselfです。
                 */
                var self = this;
                /**
                 * 新しいページCSS用のリンク要素を生成してheadにappendします。
                 */
                this.createAndAppendNewPageCssLink();
                /**
                 * 新しいcssをセットします。
                 */
                this.setNewCssToChangedPage(this.url);
                /**
                 * スライドメニューの開閉を行うイベントをセットします。
                 * 当面は、menuAnchorのセットだけです。
                 * (*mainContainerへフリックイベントのセットを行うこともできます。:未搭載)
                 *
                 * headLoad時にセットできます。
                 */
                var setEventListenerToSlide = function() {
                    //menuアンカーにイベントをセット
                    //クリックイベントだと、android標準ブラウザのイベント取得が一度目では発火しません。
                    self.container.menuAnchor.addEventListener(EVENT_NAME, self, false);
                    //XXX:フリックイベントに対応する場合はここにイベントを追記します。
                    self.container.mainContainer.addEventListener('touchstart', self, false);
                    self.container.mainContainer.addEventListener('touchmove', self, false);
                    self.container.mainContainer.addEventListener('touchend', self, false);
                    self.container.mainContainer.addEventListener('click', self, false);

                };
                var appendContainerToBody = function() {
                    //ここでのthisはContainerクラスです。(Containerクラスの内部でcallされています)
                    //DOMContentの解析が終わってから実行します。
                    //退避したthisを使う。*イベントリスナでのthisがdocumentになってしまうため。
                    var setWhenDOMContentLoaded = function() {
                        //ここでのthisはDocumentです。
                        //Pageを指すにはselfを使います。
                        //-------------------------------------------------

                        /**
                         * 余計なローディングを停止します。停止のタイミングはここでいいのか?
                         */
                        window.stop();
                        //fragmentを生成して、既存のコンテンツを必要な部分のみfragmentに移動します。
                        var sectionFragment = document.createDocumentFragment();
                        sectionFragment.appendChild(document.getElementById('maincol'));
                        var footerFragment = document.createDocumentFragment();
                        footerFragment.appendChild(document.getElementById('footer'));

                        //別途submenuを生成しますので、コメントアウト
                        /*
                        var subFragment = document.createDocumentFragment();
                        subFragment.appendChild(document.getElementById('navigation'));
                        subFragment.appendChild(document.getElementById('side-navi'));
                        */
                        //既存コンテンツのbodyをなくし、新しいコンテナを書き込みます。
                        document.body.innerHTML = "";
                        document.body.appendChild(self.container.outerContainer);
                        //新しいコンテナに退避しておいた既存コンテンツを書き込みます。
                        self.container.sectionContainer.appendChild(sectionFragment);
                        self.container.footerContainer.appendChild(footerFragment);
                        // self.container.subContainer.appendChild(subFragment);

                        /**
                         * サイドメニューを生成します。
                         */
                        self.crateAneAppendSideMenu();
                        //メニューアンカーにイベントリスナーをセットします。
                        setEventListenerToSlide();

                        //mainContainer内のアンカーイベントを登録します。
                        self.setSectionContainerLinksControll();
                        self.setFooterContainerLinksControll();
                        //subContainer内のアンカーイベントを登録します。
                        self.setSubContainerLinksControll();

                    };
                    if (document.body) {
                        setWhenDOMContentLoaded();
                    } else {
                        document.addEventListener('DOMContentLoaded', setWhenDOMContentLoaded, false);
                    }
                };
                //containerの生成が完了して、なおかつ、DOMContentLoadedになってからコンテナをセットするためにcallbackを使います。
                this.container = new Container(appendContainerToBody);
                //コンテンツを表示します。
                this.setCSSbodyBlock();
            },
            secondTimeProcess : function(url) {
                //console.log("遷移ページです。");
                //ajaxでコンテンツを取得します。取得結果はhandleEvent(event)で取得されます。
                var self = this;
                /**
                 * 新しいcssをセットします。
                 */
                this.setNewCssToChangedPage(url);
                var xhr = null;

                var xhrCallback = function(event) {
                    //この内部でのthisはXMLHttpRequestインスタンスをさします。
                    //TODO:ローディングマークを表示するにはここに記述を追加します。

                    if (xhr.status === 200 && xhr.readyState === 4) {

                        //console.log(this.responseText);
                        //引数にresponseTextをDOMに変更したhtmlDocumentを渡してsetContentsTosectionContainerを実行します。
                        var htmlDoc = self.getDomFromText(xhr.responseText);
                        self.setContentsTosectionContainer(htmlDoc);
                    }
                };
                xhr = new XMLHttpRequest();
                xhr.open('GET', url, true);
                xhr.addEventListener('readystatechange', xhrCallback, false);
                xhr.send();

            },
            crateAneAppendSideMenu : function() {
                var fragment = document.createDocumentFragment();
                var ul = document.createElement('ul');
                fragment.appendChild(ul);
                for (var i = 0; i < SUBMENU_JSON.length; i++) {
                    var li = document.createElement('li');
                    var a = document.createElement('a');
                    /**
                     * 文字を配置するためにcreateTextNodeを実行します。
                     * innerTextでセットすると、android-firefoxで表示しません。
                     */
                    var txt = document.createTextNode(SUBMENU_JSON[i].text);
                    a.appendChild(txt);
                    li.appendChild(a);
                    li.id = SUBMENU_JSON[i].id;
                    a.href = SUBMENU_JSON[i].href;

                    ul.appendChild(li);
                }
                this.container.subContainer.appendChild(fragment);
            },
            createAndAppendNewPageCssLink : function() {
                this.cssLink = document.createElement('link');
                this.cssLink.rel = "stylesheet";
                this.cssLink.className = CLASS_NAME;
                document.head.appendChild(this.cssLink);
            },
            setSubContainerLinksControll : function() {
                var self = this;
                var callback = function(event) {
                    event.preventDefault();
                    self.initialize(event.target.href);
                    //スライドメニューを戻します。
                    self.moveSlideMenu();
                };
                //subContainerからアンカー要素を抽出します。
                var targetContainer = self.container.subContainer;
                var links = targetContainer.getElementsByTagName('a');
                for (var i = 0; i < links.length; i++) {
                    var link = links[i];
                    link.addEventListener(EVENT_NAME, callback, false);
                }
            },
            setSectionContainerLinksControll : function() {
                var self = this;
                var callback = function(event) {
                    event.preventDefault();
                    self.initialize(event.target.href);
                    //メインコンテンツの場合はスライドメニューの開閉はありません。
                };
                //sectionContainerからアンカータグを抽出します。
                var targetContainer = self.container.sectionContainer;
                var links = targetContainer.getElementsByTagName('a');
                for (var i = 0; i < links.length; i++) {
                    var link = links[i];
                    link.addEventListener(EVENT_NAME, callback, false);
                }
            },
            setFooterContainerLinksControll : function() {
                var self = this;
                var callback = function(event) {
                    event.preventDefault();
                    self.initialize(event.target.href);
                    //メインコンテンツの場合はスライドメニューの開閉はありません。
                };
                //footerContainerからアンカータグを抽出します。
                var targetContainer = self.container.footerContainer;
                var links = targetContainer.getElementsByTagName('a');
                for (var i = 0; i < links.length; i++) {
                    var link = links[i];
                    link.addEventListener(EVENT_NAME, callback, false);
                }
            },
            moveSlideMenu : function() {
                //スタイルシート(newContainer)にsubContainer.style.visibility:hiddenを設定しておきます。
                var target = this.container.mainContainer;
                var callback = function(event) {
                    //console.log(event);
                };

                // XXX:検査する順序は以下の通りにしておく必要があります。逆にすると初回アクセス時に動作しません。
                //!初回アクセス時にはスタイルleftの値は""が戻る.理由は不明。
                if (target.style.left === '50%') {
                    target.setAttribute('style', 'left:0px;');
                } else {
                    target.setAttribute('style', 'left:50%;');
                }
            },
            setHeightToContainers : function(self) {
                /*
                * 動的な高さが取れない。既存のスタイル設定の影響か?--違う。
                * 実行するタイミングが悪かった。コンテンツの配置がすべて完了してから実行するよう変更しました。
                * つまり、window.onloadイベント発火時にメソッド実行します。
                * しかし、まだ、android-firefoz,PC-operaなどで、コンテンツの高さより、若干小さくコンテンツ設定してしまっております。修正必要。
                */

                //メインコンテンツ要素の高さの合計をセット
                var mainClientHeight = 0;
                var subClientHeight = 0;
                var MARGIN = 0;
                self.container.mainContainer.style.height = 'auto';
                self.container.subContainer.style.height = 'auto';
                console.log("mainContainer.clientHeight:" + self.container.mainContainer.clientHeight);
                mainClientHeight = self.container.mainContainer.clientHeight;
                subClientHeight = self.container.subContainer.clientHeight;
                var contents_height = mainClientHeight > subClientHeight ? mainClientHeight : subClientHeight;
                self.container.mainContainer.setAttribute('style', 'height:' + (contents_height + MARGIN) + 'px;');
                self.container.contentsContainer.setAttribute('style', 'height:' + (contents_height + MARGIN) + 'px;');
                self.container.outerContainer.setAttribute('style', 'height:' + (contents_height + MARGIN ) + 'px;');
            },

            setCSSbodyBlock : function() {
                //DOMContentの解析が終わってから実行します。
                var setBlock = function() {
                    document.body.setAttribute('style', 'display:block !important;');
                };
                if (document.body) {
                    setBlock();
                } else {
                    document.addEventListener('DOMContentLoaded', setBlock, false);
                }
            },

            //TODO:ここをjsonファイルからセットする要素を決めることに変更すること
            setContentsTosectionContainer : function(newDom) {
                //DOMContentの解析が終わってから実行します。
                var self = this;
                var set = function() {
                    var main = newDom.getElementById('maincol');
                    self.container.sectionContainer.innerHTML = "";
                    /**
                     * main.innerHTMLではなくouterHTMLにして解決
                     */
                    self.container.sectionContainer.innerHTML = main.outerHTML;

                    //ここでコンテナの動的スタイルをセットします。
                    self.setHeightToContainers(self);
                    //新規コンテンツのリンクにajaxイベントをセットします。
                    //sectionContainer内のアンカーイベントを登録します。
                    self.setSectionContainerLinksControll();
                };
                if (document.body) {
                    set();
                } else {
                    document.addEventListener('DOMContentLoaded', set, false);
                }
                /**
                 * 動的スタイルでコンテンツの高さを設定します。
                 */

            },
            getDomFromText : function(txt) {
                var htmlDoc;
                htmlDoc = document.implementation.createHTMLDocument('dom');
                htmlDoc.documentElement.innerHTML = "<div>" + txt + "</div>";
                console.log(htmlDoc);
                return htmlDoc;
            },
            /**
             * 既存のCSSファイルをすべて無効にします。
             * その上でremoveします。
             * 【注意点】新しいスマホ用CSSファイルかどうかの判断をCLASS_NAME値で行っています。
             * CSSファイルを新規追加する際は必ず「CLASS_NAME]と同じくclassに設定するようにします。
             * これを忘れると、必要なスマホ用のCSSファイルもremoveしてしまい、スタイル反映されなくなります。
             */
            removeDefaultCssDisable : function() {
                var head = document.head;
                var sheets = document.getElementsByTagName('link');
                for (var i = 0; i < sheets.length; i++) {
                    var sheet = sheets[i];
                    if (sheet.rel === "stylesheet") {
                        /**
                         * スマホ用のCSSファイルかどうかを判別します。
                         */
                        if (sheet.className !== CLASS_NAME) {
                            console.log(sheet);
                            sheet.setAttribute('disabled', true);
                            /**
                             * removeしないと、android-firefoxで既存cssが無効にりません。
                             */
                            head.removeChild(sheet);
                        }
                    }
                }
            },
            /**
             * ページごとにセットするCSSのsrcを切り替えます。
             * この部分でcssファイルの読み込みエラーが発生するときは
             * 1)static値のPROGRAM_Directoryの値が間違っている。
             * 2)static値のPAGE_CSS_JSONの値が間違っているか追記されていない。
             * 3)ページのcssファイルが存在しない。
             * です。
             */
            setNewCssToChangedPage : function(url) {
                var baseURI = document.baseURI;
                var pageIndex = url.split(baseURI)[1];
                this.cssLink.href = PROGRAM_Directory + '/' + PAGE_CSS_JSON[pageIndex];
                console.log(this.cssLink.href);

            },
            swipe : {
                startX : 0,
                diffX : 0,
                startTime : 0,
                endTime : 0,
                swipedFlag : false

            },
            //Page.handleEvent
            handleEvent : function(event) {
                //menuAnchorタッチ時のメニュー開閉を行います。
                /*
                 var div = document.createElement('div');
                 this.container.topContainer.appendChild(div);
                 div.setAttribute('style', 'background:white;z-index:11;position:relative;');
                 var mLog = function(str) {
                 var p = document.createElement('p');
                 var str = 'イベント内容:' + str;
                 var txtNode = document.createTextNode(str);
                 p.appendChild(txtNode);
                 div.appendChild(p);
                 };
                 */
                if (event.target === this.container.menuAnchor) {
                    if (event.type === EVENT_NAME) {
                        this.moveSlideMenu();
                    }
                }
                /**
                 * contentsContainerへのフリックイベントに対応します。
                 */
                if (event.type != 'click') {
                    // event.cancelBubble = true;
                    if (this.swipe.swipedFlag === false) {

                        if (event.target.offsetParent === this.container.mainContainer) {
                            if (event.targetTouches.length === 1) {

                                if (event.type === "touchstart") {
                                    var touch = event.targetTouches[0];
                                    this.swipe.startX = touch.pageX;
                                    this.swipe.startTime = event.timeStamp;
                                    // mLog(this.swipe.startX + ":" + this.swipe.startTime);
                                }
                                if (event.type === "touchmove") {
                                    // mLog(event.type + ":" + event.target.offsetParent.id + ":" + this.swipe.startX);
                                    var touch = event.targetTouches[0];
                                    this.swipe.diffX = touch.pageX - this.swipe.startX;
                                    this.swipe.endTime = event.timeStamp;
                                    // mLog("diffX:" + this.swipe.diffX + ":timediff:" + (this.swipe.endTime - this.swipe.startTime));
                                    if (this.swipe.diffX >= 50) {
                                        if ( (this.swipe.endTime - this.swipe.startTime) <= 400) {
                                            // mLog("SWIPE!!!");
                                            event.preventDefault();
                                            this.swipe.swipedFlag = true;
                                            this.moveSlideMenu();
                                        }
                                    }
                                }
                            }
                        }

                        if (event.type === "touchend") {
                            // mLog(event.type);
                            this.swipe.startX = 0;
                            this.swipe.diffX = 0;
                            this.swipe.startTime = 0;
                            this.swipe.endTime = 0;

                        }
                    } else {
                        /**
                         * スライドメニューを閉じる
                         */
                        if (event.target.offsetParent === this.container.mainContainer) {
                            if (event.targetTouches.length === 1) {

                                if (event.type === "touchstart") {
                                    var touch = event.targetTouches[0];
                                    this.swipe.startX = touch.pageX;
                                    this.swipe.startTime = event.timeStamp;
                                    // mLog(this.swipe.startX + ":" + this.swipe.startTime);
                                }
                                if (event.type === "touchmove") {
                                    // mLog(event.type + ":" + event.target.offsetParent.id + ":" + this.swipe.startX);
                                    var touch = event.targetTouches[0];
                                    /**
                                     * ここが開くときの逆
                                     */
                                    this.swipe.diffX = this.swipe.startX - touch.pageX;
                                    this.swipe.endTime = event.timeStamp;
                                    // mLog("diffX:" + this.swipe.diffX + ":timediff:" + (this.swipe.endTime - this.swipe.startTime));
                                    if (this.swipe.diffX >= 15) {
                                        if ( (this.swipe.endTime - this.swipe.startTime) <= 400) {
                                            // mLog("SWIPE!!!");
                                            event.preventDefault();
                                            /**
                                             * 閉じるときはfalseにセット
                                             */
                                            this.swipe.swipedFlag = false;
                                            this.moveSlideMenu();
                                        }
                                    }
                                }
                            }
                        }

                        if (event.type === "touchend") {
                            mLog(event.type);
                            this.swipe.startX = 0;
                            this.swipe.diffX = 0;
                            this.swipe.startTime = 0;
                            this.swipe.endTime = 0;

                        }
                    }
                }
            }
        };
        Container = function(callback) {
            this._callback = callback;

            this.outerContainer = null;
            this.topContainer = null;
            this.contentsContainer = null;
            this.mainContainer = null;
            this.sectionContainer = null;
            //ver3.5にて追記しました。3/12
            this.subContainer = null;
            this.footerContainer = null;
            //ver3.5にて追記しました。3/12
            this.menuAnchor = null;

            this.initialize();
        };
        Container.prototype = {
            initialize : function() {

                this.createContainers();
                this.setIdToContainers();
                this.appendContainers();
                this.createAndAppendMenuAssy();

                this._callback();
            },
            createContainers : function() {
                this.outerContainer = document.createElement('div');
                this.topContainer = document.createElement('header');
                this.contentsContainer = document.createElement('div');
                this.mainContainer = document.createElement('div');
                this.sectionContainer = document.createElement('section');
                this.subContainer = document.createElement('nav');
                this.footerContainer = document.createElement('footer');
            },
            setIdToContainers : function() {
                //set id
                this.outerContainer.id = "outerContainer";
                this.topContainer.id = "topContainer";
                this.contentsContainer.id = "contentsContainer";
                this.mainContainer.id = "mainContainer";
                this.sectionContainer.id = "sectionContainer";
                this.subContainer.id = "subContainer";
                this.footerContainer.id = "footerContainer";
            },
            appendContainers : function() {
                //構成
                this.outerContainer.appendChild(this.topContainer);
                this.outerContainer.appendChild(this.contentsContainer);
                this.contentsContainer.appendChild(this.subContainer);
                this.contentsContainer.appendChild(this.mainContainer);
                this.mainContainer.appendChild(this.sectionContainer);
                this.mainContainer.appendChild(this.footerContainer);
            },
            createAndAppendMenuAssy : function() {
                //menuAnchorの要素生成
                var menuAssy = document.createElement('div');
                var span = document.createElement('span');
                span.innerHTML = "&equiv;";

                this.menuAnchor = document.createElement('a');
                this.menuAnchor.innerHTML = "MENU";

                //append
                this.menuAnchor.appendChild(span);
                menuAssy.appendChild(this.menuAnchor);
                this.topContainer.appendChild(menuAssy);
            },

            getouterContainer : function() {
                return this.outerContainer;
            }
        };

        /**
         * @constructor
         */
        Device = function() {
            this.SMARTPHONES = ['Android', 'iphone', 'Windows Phone', 'BlackBerry', 'IEMobile'];
            this.TABLETS = ['iPod', 'iPad'];
            //このプログラムでは未使用(タブレット対応のときに使う)
            this.TARGETMAXWIDTH = 767;
            //このサイズ以下のときにプログラム対象とします。
            this._userAgent = "";
            this._deviceWidth = 0;

            //初期化を実行します。
            this.initialize();
        };
        Device.prototype = {
            /**
             * コンストラクタです。
             */
            initialize : function() {
                //ユーザーエージェントを調査して_userAgentに格納します。
                this.checkTargetUserAgent();
                //デバイスの画面幅を調査して_deviceWidthに格納します。
                this.checkDeviceWidth();
            },
            checkTargetUserAgent : function() {
                this._userAgent = navigator.userAgent;
            },
            checkDeviceWidth : function() {
                //htmlに事前にviewportをセットしてあることが前提です。
                this._deviceWidth = document.documentElement.clientWidth;
            },
            /**
             * このスマホ化プログラムの対象ならtrueを返します。
             */
            isTargetDevice : function() {
                //デバイスのユーザーエージェントがandroidであっても画面サイズの大きいタブレットがあるので画面サイズも判定します。
                for (var i = 0; i < this.SMARTPHONES.length; i++) {
                    if (this._userAgent.indexOf(this.SMARTPHONES[i]) > 0) {
                        if (this._deviceWidth <= this.TARGETMAXWIDTH) {
                            return true;
                        }
                    }
                }
                return false;
            },
            //operaminiかどうかを検査。operaminiならtrueを返す。
            isOperamini : function() {
                if ( typeof operamini !== 'undefined') {
                    if (operamini) {

                        return true;
                    }
                }
                return false;
            }
        };
        /**
         * @constructor
         */
        Main = function() {
            this.device = {};
            this.page = {};

            this.start();
        };
        Main.prototype = {
            start : function() {
                //Deviceクラスをインスタンス化してデバイスの基本情報を取得、格納します。
                this.device = new Device();

                //今回のスマートフォンの対象かどうかを調査して戻り値がfalseなら停止します。
                //TODO:今はテストとして、PCでも動作させるよう、分岐しています。
                //↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓
                if (TESTFLAG != true) {
                    if (this.device.isTargetDevice() === false) {
                        this.stop();
                        return;
                    };
                }
                /**
                 * operaminiなら停止します。
                 * ver3.6にて追記。
                 */
                if (this.device.isOperamini() === true) {
                    this.stop();
                    return;
                }

                //チェックした結果を格納しておきます。後のプロセスで使用します。
                this.page = new Page(this.device);

            },
            stop : function() {
                //メモリ解放など実行する
                this.device = null;
                this.page = null;
                //body.styleをblockに変更して(既存)コンテンツを表示します。
                var setBlock = function() {
                    document.body.setAttribute('style', 'display:block !important;');
                };
                if (document.body) {
                    setBlock();
                } else {
                    document.addEventListener('DOMContentLoaded', setBlock, false);
                }
                //console.log('プログラムを停止しました');
            }
        };

        new Main();
    }());

//(c) Copyright 2014 鴨頭 剛. All Rights Reserved.