コントロール用レイヤー(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); }());