たぼさんの部屋

いちょぼとのんびり

コントロール用レイヤー(Main_21.js)

これはiframeを使う為に

コントロール用レイヤーを使ってリンクコントロールをしようとういうもの。

  • pointはここ。touchstartイベント時に一時的にレイヤーのdisplay.noneにする
this.layer.style.display = "none";
var elm = document.elementFromPoint(x, y - scrollY);
this.layer.style.display = "block";
console.log(elm);

途中作成

Main_21.js

/*jslint nomen: true*/
( function() {"use strict";
        var host = document.location.host;
        //host : "php.efolab.com"という形式。
        var protocol = document.location.protocol;
        //protocol : "http:"という形式
        var baseuri = protocol + "//" + host + "/";
        // baseuri : http://php.efolab.com/ という形式。
        var targetDomain = ["vino-form.com", "vino-form.efolab.com"];

        var pagePath = baseuri + "EFOLAB/_server/_pages";
        //submenu , footerのa要素に付与しているclass名です。
        var menuClassName = "menu";

        //origin : "http://php.efolab.com"形式
        //var origin = document.location.origin;   //androidブラウザでは取得できないため利用停止。

        //コンテナ・要素類の定義
        var _outerContainer;
        var _pageContaner;
        var _subContainer;
        var _footerContainer;
        var _inquiryAssyContainer;
        var _mainContainer;
        var _contentsContainer;
        var _menuAnchor;
        var _iframe;
        var _topContainer;

        /*
        * Class
        */
        //class定義
        var SlideController;
        var WrappingLayer;
        var AutoFontSpan;
        var IframeController;
        var ContainerController;
        var LinkController;
        var MenuAnchorEventHandler;
        var SwipeEventHandler;
        //instance定義
        var slideController;
        var wrappingLayer;
        var iframeController;
        var containerController;
        var linkController;
        var menuAnchorEventHandler;
        var swipeEventHandler;

        //------------------------------------------------------------------//
        //  IframeControler   start
        //
        //------------------------------------------------------------------//

        /**
         *@constructor
         */
        IframeController = function() {
        };
        IframeController.prototype = {
            initialSetting : function() {

                //初期に(container.cssにて)hiddenにしてあるのをvisibleに
                _iframe.style.visibility = "visible";
                //コンテナ全体の高さをセット
                containerController.setContainerHeight();

                wrappingLayer.off();

                //00の位置へスクロールします。
                window.scrollTo(0, 0);
            },
            /*
             * postMessageを受信
             */
            handleEvent : function(event) {
                console.log(event.type);
                var json = JSON.parse(event.data);
                if (json.height) {
                    //iframeページのロード時
                    _iframe.style.height = json.height + "px";

                    this.initialSetting();

                } else if (json.flick) {
                    //iframeのdocumentをフリックした時
                    console.log(json.flick);

                    slideController.slideMenu(json.flick);
                }
            }
        };
        /**
         *@constructor
         */
        ContainerController = function() {

        };
        ContainerController.prototype = {
            initialSetting : function() {
                //全体のフォント調節をセットします。(iframe内のフォント調節はiframe.jsで実行しています。)
                var elms = document.body.getElementsByTagName('span');
                for (var i = 0; i < elms.length; i++) {
                    if (elms[i].getAttribute('size')) {
                        new AutoFontSpan(elms[i], elms[i].getAttribute('size'));
                    }
                }

                //フリックコントローラをセット
                slideController.setFlickListener(_mainContainer);
            },
            setContainerHeight : function() {
                //初期化:clientHeightを取得できるように。
                _subContainer.style.height = 'auto';
                _mainContainer.style.height = 'auto';

                var subHeight = _subContainer.clientHeight;
                var mainHeight = _mainContainer.clientHeight;

                //subContainer , mainContainer の高さの長い方をcontenteContainerのheightに設定します。
                var currentHeight = (subHeight > mainHeight) ? subHeight : mainHeight;
                _contentsContainer.style.height = currentHeight + 'px';

                //
                //  wrappingLayerの高さをセット
                //
                wrappingLayer.setHeight(currentHeight);

                //親要素:contentsContainerにセットしたheightを強制的に継承するようにinheritを設定します。
                _subContainer.style.height = 'inherit';
                _mainContainer.style.height = 'inherit';
            },
            handleEvent : function(event) {
                console.log(event.type);
                if (event.type === "load") {
                    this.initialSetting();
                }
            }
        };
        /**
         * @constructor
         */
        MenuAnchorEventHandler = function(sourceAnchor) {
            this.sourceAnchor = sourceAnchor;
            this.initialize();
        };
        MenuAnchorEventHandler.prototype = {
            initialize : function() {

                if ("ontouchstart" in window) {
                    this.sourceAnchor.addEventListener('touchstart', this, false);
                    this.sourceAnchor.addEventListener('touchend', this, false);

                } else {
                    this.sourceAnchor.addEventListener('click', this, false);
                }
            },
            handleEvent : function(event) {
                //疑似要素のタッチの場合も補足するためにparentNodeも調査します。
                //menuタッチ時の処理
                switch(event.type) {
                    case "touchstart":
                        //--------------style set---------------------
                        this.sourceAnchor.style.backgroundColor = "rgb(255,248,248)";
                        //ティッカーを非表示にするためクラス名を削除します。
                        document.getElementById('menuTicker').style.display = "none";
                        break;

                    case "touchend":
                        //------------style--------------------------
                        this.sourceAnchor.style.backgroundColor = "white";
                        //スライドメニューを開閉します。
                        slideController.slideMenu();

                        break;
                }
            }
        };

        /**
         * @constructor
         */
        SwipeEventHandler = function(sourceContainer) {
            this.container = sourceContainer;

            this.initialize();
        };
        SwipeEventHandler.prototype = {
            initialize : function() {
                this.container.addEventListener('touchstart', this, false);
                this.container.addEventListener('touchmove', this, false);
                this.container.addEventListener('touchend', this, false);
            },
            handleEvent : function(event) {

                switch(event.type) {
                    case "touchstart":
                        this.start = {
                            pageX : event.touches[0].pageX,
                            pageY : event.touches[0].pageY,
                            time : Number(new Date())
                        };
                        //初期化
                        this.movedX = 0;
                        //onTouchMoveで利用するための初期化設定です。
                        this.isScrolling = undefined;
                        break;
                    case "touchmove":
                        // タッチが1本のときだけ実行します。
                        if (event.touches.length > 1 || event.scale && event.scale !== 1) {
                            return;
                        }
                        var pageX = event.touches[0].pageX;
                        var pageY = event.touches[0].pageY;
                        this.deltaX = pageX - this.start.pageX;
                        this.deltaY = pageY - this.start.pageY;

                        //スクロールかどうかの判定です。スクロールイベントは連続して発生するため、onTouchStart-onTouchMove-onTouchEndの一連の動作の中で、最初に一度だけテストします。
                        if ( typeof this.isScrolling === 'undefined') {
                            this.isScrolling = !! (this.isScrolling || Math.abs(this.deltaX) < Math.abs(this.deltaY) );
                        }
                        //スクロールではないとき
                        if (!this.isScrolling) {
                            slideController.move(this.deltaX - this.movedX);
                            this.movedX = this.deltaX;
                        }

                        break;

                    case "touchend":
                        //スクロール判定
                        if (this.isScrolling) {
                            //スクロール時にはなにもしません。
                            return false;
                        }
                        //フリック判定
                        var deltaTime = Number(new Date()) - this.start.time;
                        if ( (deltaTime < 100) && (Math.abs(this.deltaX) > 40 )) {
                            console.log("Flick");

                            //スライドメニュー操作
                            if (this.deltaX > 0) {
                                slideController.slideMenu("open");
                            } else {
                                slideController.slideMenu("close");
                            }
                            return;
                        }
                        //スラードムーブ判定
                        if (this.movedX !== 0) {
                            slideController.slideMenu();

                            return;
                        }
                        //
                        //  リンクタッチ
                        //
                        linkController.handleEvent(event);

                        break;
                }
            }
        };

        /**
         * AutoFontSpan
         * @constructor
         */
        AutoFontSpan = function(target, size) {
            //sizeは1が普通サイズ
            this.target = target;
            this.size = size;

            var self = this;
            window.addEventListener('resize', function() {
                self.setSize.call(self);
            }, false);

            this.setSize();
        };
        AutoFontSpan.prototype = {
            BASE_RATIO : 1 / 360,

            setSize : function() {
                try {
                    this.target.style.fontSize = Math.round(document.documentElement.clientWidth * this.BASE_RATIO * this.size * 100) + '%';
                } catch(e) {
                    alert(e);
                }
            }
        };
        /**
         * LnkController
         * @constructor
         * @param container {Container}
         * @param callback {function}
         */
        var LinkController = function() {
            this.anchor = undefined;
        };
        LinkController.prototype = {
            set : function(anchor) {
                this.anchor = anchor;
            },

            /*
             * ページ遷移
             * アンカー要素のイベントを受け取り処理します。
             */
            handleEvent : function(event) {
                console.log("ページ遷移");

                //img要素を下位に持っているアンカー要素の場合にa要素を取得する関数。
                var getAnchor = function(target) {
                    try {
                        var anchor = undefined;
                        if (target.href) {
                            anchor = target;
                        } else {
                            anchor = getAnchor(target.parentNode);
                        };

                    } catch(e) {

                    }
                    return anchor;
                };

                if (event.type === "touchend") {

                    /*
                    * スクロールではなく、タッチのとき
                    */
                    //スライドメニューを閉じます。
                    slideController.closeSlide();

                    var isTel = function(anchor) {
                        console.log("---protocol振り分け:anchor.protocol === 'tel: ---'" + (anchor.protocol === "tel:"));
                        console.log("anchor.protocol=" + anchor.protocol);

                        return anchor.protocol === "tel:";
                    };
                    var isMenuLink = function(anchor) {
                        console.log("---menuからのリンク判定 : anchor.className===menuClassName ---" + (anchor.className === menuClassName));
                        console.log("className=" + anchor.className);
                        console.log("menuClassName=" + menuClassName);

                        return anchor.className === menuClassName;
                    };
                    var isDomain = function(anchor) {
                        console.log("--- 内部サイトかどうかの判別:anchor.host === host ---" + (anchor.host === host));
                        console.log("anchor.host =" + anchor.host);
                        console.log("host=" + host);

                        return anchor.host === host;

                    };
                    var isTargetDomain = function(anchor) {
                        var isTarget = false;
                        for (var i = 0; i < targetDomain.length; i++) {
                            console.log("--- 対象の他ドメインかどうかの判別:anchor.host === targetDomain[" + i + "] ---" + (anchor.host === targetDomain[i]));
                            console.log("anchor.host =" + anchor.host);
                            console.log("targetDomain[" + i + "]=" + targetDomain[i]);
                            if (anchor.host === targetDomain[i]) {
                                isTarget = true;
                            }
                        }
                        return isTarget;
                    };

                    /*
                    * 内部サイトか、対象の他ドメインか、対象外の他ドメインかによって
                    * 処理を分岐します。
                    */

                    //アンカー要素を抽出します。
                    var anchor = getAnchor(this.anchor);
                    if(anchor===undefined){
                        console.log("a要素ではないため中止");
                        return;
                    }

                    //style
                    anchor.style.color = "red";
                    // anchor.className = "checkMark";
                    console.log("----リンクの判別開始----");

                    if (isTel(anchor)) {
                        //電話プロトコルのとき。preventDefaultせずに通常動作させます。
                        return;
                    }

                    //preventDefault実行
                    event.preventDefault();

                    if (isDomain(anchor)) {
                        //内部サイトの場合
                        /*
                         * iframe内のリンクかどうかの判別を行います。
                         * submenu,fotterのmenuからのリンクの場合はanchor.className ="menu"です。
                         */

                        if (isMenuLink(anchor)) {
                            //submenu,footerからのリンクです。
                            //画面遷移します。
                            console.log("内部サイト:menuからのリンク:遷移先=" + pagePath + anchor.pathname);

                            //pagePath:_server/_pages/ディレクトリのファイルを開きます。
                            _iframe.src = pagePath + anchor.pathname;

                        } else {
                            //iframeからのリンクです。
                            //画面遷移します。
                            console.log("内部サイト:iframeからのリンク:遷移先=" + anchor.href);
                            _iframe.src = anchor.href;
                        }
                        //ifrrameの高さを初期化します。
                        _iframe.style.height = window.screen.height;
                        //読み込み中レイヤーを表示します。
                        wrappingLayer.on();

                    } else {
                        /*
                         * 他のドメインです。
                         * 対象の他ドメインか対象外の他ドメインかの判別を行います。
                         * あらかじめ記述してあるtargetDomain配列とリンク先のhost名が同一かどうかを調査します。
                         */

                        if (isTargetDomain(anchor)) {
                            //対象の他ドメインの場合
                            console.log("対象の他ドメイン");

                            //読み込み中レイヤーを表示します。
                            loadingLayerController.on();
                            //ifrrameの高さを初期化します。
                            _iframe.style.height = window.screen.height;

                            //画面遷移します。
                            var targetFile = anchor.getAttribute('href');
                            try {
                                _iframe.src = targetFile;

                            } catch(e) {
                                console.log(e.stack);
                            }

                        } else {
                            try {
                                //対象外の他ドメインの場合
                                console.log("対象外の他ドメイン:" + anchor.href);
                                //androidブラウザで動作しないため、同一のタブで開きます。
                                // window.open(anchor.href, '_blank');
                                location.href = anchor.href;

                            } catch(e) {
                                alert(e.stack);
                            }
                        }
                    }

                    //onclick属性があれば、それを実行します。
                    if (anchor.onclick) {
                        console.log('onclickの属性を実行しました。');
                        anchor.onclick();
                    }
                    //style 済みの色に変更。
                    anchor.style.color = "gray";
                    // anchor.className = "checkMark";
                }

            },
        };
        var WrappingLayer = function(wrapContainer) {
            this.wrapContainer = wrapContainer;
            this.layer = undefined;
            this.loadingDIV = undefined;

            this.initialize();

        };
        WrappingLayer.prototype = {
            initialize : function() {
                var screenHeight = window.screen.height;

                //iframeの上に新しいレイヤーをセットします。
                var layer = document.createElement('div');
                var loadingDIV = document.createElement('div');
                var img = document.createElement('img');
                img.src = baseuri + "EFOLAB/_script/img/loading.gif";
                var p = document.createElement('p');
                p.textContent = "読み込み中...";

                loadingDIV.appendChild(img);
                loadingDIV.appendChild(p);
                layer.appendChild(loadingDIV);

                loadingDIV.style.textAlign = "center";
                loadingDIV.style.position = "fixed";
                loadingDIV.style.width = "100%";
                loadingDIV.style.top = (screenHeight) / 2;

                layer.setAttribute("style", "position:absolute;z-index:30;width:100%;");
                var wrapContainerHeight = this.wrapContainer.style.height;
                layer.style.height = wrapContainerHeight;

                loadingDIV.style.display = "none";

                this.wrapContainer.appendChild(layer);

                this.layer = layer;
                this.loadingDIV = loadingDIV;
            },
            on : function() {
                //高さを再取得して表示
                var wrapContainerHeight = this.wrapContainer.style.height;
                this.layer.style.height = wrapContainerHeight;
                this.layer.style.backgroundColor = 'rgba(255,255,255,0.9)';

                this.loadingDIV.style.display = "block";
            },
            off : function() {
                this.layer.style.backgroundColor = 'rgba(0,255,255,0.5)';

                //隠す
                this.loadingDIV.style.display = "none";
            },
            setHeight : function(height) {
                this.layer.style.height = height + "px";
            },
            handleEvent : function(event) {

                if (event.type === "touchstart") {
                    var x = event.touches[0].pageX;
                    var y = event.touches[0].pageY;

                    var scrollY = document.body.scrollTop;

                    console.log(x + "," + y);
                    console.log("scroll=" + scrollY);

                    this.layer.style.display = "none";
                    var elm = document.elementFromPoint(x, y - scrollY);
                    this.layer.style.display = "block";
                    console.log(elm);

                    //対象がiframeのときはiframeにpostMessageを送信してelmを取得してもらう。
                    if (elm === _iframe) {
                        var iframeY = _iframe.getBoundingClientRect().top;
                        var iframeX = _iframe.getBoundingClientRect().left;
                        var message = {
                            "position" : {
                                "x" : x - iframeX,
                                "y" : y - scrollY - iframeY
                            }
                        };
                        message = JSON.stringify(message);
                        _iframe.contentWindow.postMessage(message, protocol + "//" + host);
                    } else {
                        linkController.set(elm);
                    }
                }
            }
        };

        /**
         *@constructor
         * @param {DOMObject} slideContainer
         * @param {DOMObject} wrapperContainer
         */
        var SlideController = function(slideContainer, wrapperContainer) {
            //スライドさせるエレメントです。
            this.slideContainer = slideContainer;
            //スライドの座標基準となるコンテナエレメントです。
            this.wrapperContainer = wrapperContainer;
            this.wrapperContainer.width = undefined;
            //引数オプションのmaxSlideRatio:スライドさせる比率。初期値0.5であればcontainerの50%のスライドです。
            this.maxSlideRatio = 0.35;
            //上記のmaxSlideRatioをもとにしたスライドさせる最大左座標です。
            this.maxSlideLeftPercent = this.maxSlideRatio * 100 + '%';
            //閉じた状態の際の左座標です。初期値は0%:これはコンテナのposition:relative設定の連携座標です。
            this.minSlideLeftPercent = '0%';

            //menuAnchorです。this.setMenuListenerの引数targetでセットします。
            this.menuElement = undefined;
            this.onCloseFunctions = [];
            this.onOpenFunctions = [];

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

                //スタイル設定の初期値を与えます。閉じた座標位置であるminSlideLeftです。
                this.slideContainer.style.left = this.minSlideLeftPercent;
                //コンテナの幅をセットします。
                this.wrapperContainer.width = this.wrapperContainer.getBoundingClientRect().width;
            },

            setFlickListener : function(target) {
                target.addEventListener('touchstart', this, false);
                target.addEventListener('touchend', this, false);
            },
            setOnOpenFunction : function(func) {
                this.onOpenFunctions.push(func);
            },
            setOnCloseFunction : function(func) {
                this.onCloseFunctions.push(func);
            },
            move : function(deltaX) {
                var currentLeftPercent = this.slideContainer.style.left;
                var percentDeltaX = deltaX / this.wrapperContainer.width * 100;

                var newLeft = parseFloat(currentLeftPercent) + percentDeltaX;
                if (newLeft > parseFloat(this.minSlideLeftPercent) && newLeft < this.maxSlideRatio * 100) {
                    this.slideContainer.style.left = newLeft + "%";
                }
            },
            /**
             * @param order {String}
             */
            slideMenu : function(order) {
                switch (order) {
                    //  from SwipeEventHandler
                    case "open":
                        this.openSlide();
                        break;
                    case "close":
                        this.closeSlide();
                        break;
                    //  from MenuAnchorHandler
                    default:
                        if (this.slideContainer.style.left === this.minSlideLeftPercent) {
                            //開く
                            this.openSlide();
                        } else if (this.slideContainer.style.left === this.maxSlideLeftPercent) {
                            //閉じる
                            this.closeSlide();
                        } else if (parseFloat(this.slideContainer.style.left) <= this.maxSlideRatio * 100 / 2) {
                            //閉じる
                            this.closeSlide();
                        } else {
                            //開く
                            this.openSlide();
                        }
                }
            },
            openSlide : function() {
                //スライドメニューを開きます。
                this.slideContainer.style.left = this.maxSlideLeftPercent;
                //open時の追加ファンクションを実行します。
                var funcs = this.onOpenFunctions;
                for (var i = 0; i < funcs.length; i++) {
                    funcs[i]();
                }
            },
            closeSlide : function() {
                //スライドメニューを閉じます
                this.slideContainer.style.left = this.minSlideLeftPercent;
                //close時の追加ファンクションを実行します。
                var funcs = this.onCloseFunctions;
                for (var i = 0; i < funcs.length; i++) {
                    funcs[i]();
                }
            }
        };

        function boot() {
            console.log('DOMContentLoaded');

            //
            //  DOM要素の取得部
            //
            _outerContainer = document.getElementById('outerContainer');
            _pageContaner = document.getElementById('pageContainer');
            _subContainer = document.getElementById('subContainer');
            _footerContainer = document.getElementById('footerContainer');
            _inquiryAssyContainer = document.getElementById('inquiryAssyContainer');
            _mainContainer = document.getElementById('mainContainer');
            _contentsContainer = document.getElementById('contentsContainer');
            _menuAnchor = document.getElementById('menuAnchor');
            _topContainer = document.getElementById('topContainer');
            _iframe = document.getElementById('iframe');

            //
            //  インスタンス生成部
            //

            //-------------------------------------------
            //  ContainerController インスタンス生成
            //-------------------------------------------
            containerController = new ContainerController();

            //-------------------------------------------
            //  IframaController インスタンス生成
            //-------------------------------------------
            iframeController = new IframeController();

            //-------------------------------------------
            //  SlideController インスタンス生成
            //-------------------------------------------
            slideController = new SlideController(_mainContainer, _contentsContainer);

            //--------------------------------------------
            //  LinkController インスタンス生成
            //--------------------------------------------
            linkController = new LinkController();

            //-------------------------------------------
            //  LoadingLayerController インスタンス生成
            //-------------------------------------------
            wrappingLayer = new WrappingLayer(_contentsContainer);

            //-------------------------------------------
            //  MenuAnchorEventHandler インスタンス生成
            //-------------------------------------------
            menuAnchorEventHandler = new MenuAnchorEventHandler(_menuAnchor);

            //-------------------------------------------
            //  SwipeEventHandler インスタンス生成
            //-------------------------------------------
            swipeEventHandler = new SwipeEventHandler(wrappingLayer.layer);

            //
            //  イベントリスナの登録部
            //

            //------------------------------------------
            //  containerController
            //  window load時
            //------------------------------------------
            window.addEventListener('load', containerController, false);

            //------------------------------------------
            //  iframeController
            //  postMessage 受信時
            //------------------------------------------
            window.addEventListener('message', iframeController, false);

            //-----------------------------------------
            //  wrappingLayer
            //-----------------------------------------
            document.addEventListener('touchstart', wrappingLayer, false);
            document.addEventListener('touchmove', wrappingLayer, false);
            document.addEventListener('touchend', wrappingLayer, false);

            wrappingLayer.on();

        }

        try {
            if (document.body) {
                boot();
            } else {
                document.addEventListener('DOMContentLoaded', boot, false);
            }

        } catch(e) {
            var retry = function() {
                document.addEventListener('DOMContentLoaded', boot, false);
            };
            retry();
        }
    }());

iframe_21.js

( function() {"use strict";
        var webMessaging = ( function() {
                var target = parent.postMessage ? parent : (parent.document.postMessage ? parent.document : undefined);
                return {
                    send : function(message) {
                        //jsonオブジェクトで記述しました。
                        var jsonMessage = JSON.stringify(message);
                        //json形式に変換
                        target.postMessage(jsonMessage, "*");
                    }
                };
            }());

 
        /**
         * AutoFontSpan
         */
        var AutoFontSpan = function(target, size) {
            //sizeは1が普通サイズ
            this.target = target;
            this.size = size;

            var self = this;
            window.addEventListener('resize', function() {
                self.resize.call(self);
            }, false);

            this.setSize();
        };
        AutoFontSpan.prototype = {
            BASE_RATIO : 1 / 360,

            setSize : function() {
                try {
                    this.target.style.fontSize = Math.round(document.documentElement.clientWidth * this.BASE_RATIO * this.size * 100) + '%';
                } catch(e) {
                    alert(e);
                }
            },
            resize : function(event) {
                this.setSize();
            }
        };

        function init() {

            //フォント調節をセットします.
            var elms = document.getElementsByTagName('span');
            for (var i = 0; i < elms.length; i++) {
                if (elms[i].getAttribute('size')) {
                    new AutoFontSpan(elms[i], elms[i].getAttribute('size'));
                }
            }

            /*
            * postMessage
            * !!修正:4/18 json形式に修正しました。(iframeのdocumentにflickイベントを設定するため)
            */
            // iframe.bodyの高scrollHeightさをpostMessageで送信します。
            var message = {
                "height" : document.body.scrollHeight
            };
            webMessaging.send(message);

        }


        window.addEventListener('load', init, false);

        //parentからの受信用
        window.addEventListener('message', function(event) {
            console.log("親からのmessage受信");
            var message = JSON.parse(event.data);
            console.log(message);
            var position = message.position;
            var x = position.x;
            var y = position.y;
            console.log("x=" + x + ",y=" + y);
            var elm = document.elementFromPoint(x, y);
            console.log(elm);
        }, false);

    }());