モーダルウィンドウといくつかの利点についてもう一度

モーダルウィンドウについてはすでに多くの文献が書かれていると思われますが、ハブに関するこの記事は私にこのトピックを書くように促していました。 ページとモーダルウィンドウの両方での水平方向のジャンプなど、多くのことは言われていません。

もちろん、コメントで登録を解除して、「そうするように」などと言ってもかまいません。すべてが最高です。 しかし、私の解説は、明確な例とコメントとともに、新しい記事のサイズにまで成長しました。

それが面白くなった人-habrakatの下で歓迎!



率直に言って、このタイプのページ上のコンテンツの表示は「モーダルウィンドウ」とは呼ばれず、私の言語は変わりません。 それでも、これらはわずかに異なるものです。 したがって、これを「クラウドコンテンツ」と呼びます。 これは、このタイプのコンテンツ表示の最も正しい定義だと思います。



したがって、私たちの主なタスク:

1)ページを修正して、高さを大きく変更しても左右に「ジャンプ」しないようにします。

2)クラウドウィンドウを開いて中央に配置し、高さを変更してもページ上のコンテンツがそのまま残るようにします。

3)キーボードのキー「上下矢印」を使用して、「クラウドウィンドウ」の垂直スクロールを実現します。

4)以前に開いたウィンドウをDOMにキャッシュして、複雑な操作や計算を実行したり、サーバーに不要な要求を行わないようにします。

5)エンドユーザーにとって最も便利なナビゲーションのためにホットナビゲーションキーを接続します(ウィンドウ間を移動する場合は左/右矢印キー、ウィンドウを閉じる場合はエスケープキー)。



ポイント4と5はパンです。



それ以外の場合は、フレームワークを使用せず、ネイティブJSで記述します。 今後、非圧縮形式のコメントなしのJSコードはわずか5 kbしかかかりません。



始めましょう。

すぐに既成の視覚的な例を示して、この記事を読むときに、何が比較され、何が議論されているかを正確に確認できるようにします。



デモの例とページに接続されたJSファイル (JSは "beaten"を開くため、アーカイブ全体をすぐにダウンロードできます )。



最初に、関数elemID()を定義します。 document.getElementByIdの構築はコードでは非常に一般的であるため、同様の関数を使用してこのエントリを短縮する方が簡単で、JSファイルの全体的な重量を大幅に削減できます。 これは、大量のコードを持つ大規模なファイルにとって特に重要です。



function elemID(e) {return document.getElementById(e);};
      
      







後で作業するオブジェクトを開始します。



 var Content = {}
      
      







最初に行うことは、ページの修正です。 これを行うために、ページのコンテンツ全体をid = "layer"のブロックにラップします



 <body id="body"> <div class="layer" id="layer"> <!--     --> </div> </body>
      
      







できた 彼のために、このブロックを中央に配置するメソッドを作成します。

 editSiteLayer:function (content) { /**    ,    - "layer" **/ if (!content) {var content = 'layer';} /** **     **   18px -     **/ var inWidth = window.innerWidth-18, /**    **/ layerWidth = elemID(content).clientWidth; /**        undefined **/ if (inWidth && layerWidth) { /**      CSS  float:left **/ elemID(content).style.cssFloat = 'left'; /** **           -    **            **/ elemID(content).style.marginLeft = (inWidth/2)-(layerWidth/2)+'px'; } }
      
      





私たちはそれを書いて一時的に忘れていました(最終的には確実に接続します)。



2番目のタスクは、「クラウドウィンドウ」を作成して開くことです。

次のようにクラウドウィンドウを開きます。

 <body id="body"> <div class="cloud" id="cloud"> <div class="cloud-layer" id="cloud-layer"> <em class="cloud-contaner" id="cloudpage__ID_"> </em> </div> </div> </body>
      
      





「クラウド」ブロックは一種の保護マスクとして機能し、サイトコンテンツをクラウドウィンドウから分離すると同時に「クラウド」にします。 CSSプロパティ:

 .cloud{ display:block; padding:0; margin:0; position:fixed; top:0; left:0; right:0; bottom:0; background: rgba(0, 0, 0, 0.795); z-index:3; overflow:auto; }
      
      





「クラウド層」ブロ​​ックは、クラウドコンテンツを持つすべてのDOM要素の「親」です。 ページの中央に固定され、プロパティの位置に設定されます。 (キーボードのキーでウィンドウをスクロールできるのはそれです)。

CSSプロパティ:

 .cloud .cloud-layer{ position:relative; float:left; width:720px; margin:0; padding:0; z-index:4; }
      
      





「cloud-contaner」ブロックは、クラウドコンテンツのコンテナです。 なぜEMタグに正確にあるのですか? その後、現在のブロックを検索し、既存のブロックをすべて非表示にするために、DOMを調べます。 タグによる検索は非常に適しています。



本当の問題を理解するために-私たちのサイトですべてのユーザーの個人的な写真を見たいと想像してください。 通常、これは行われます。最初に写真をクリックすると、サーバーにhttpリクエストが行われ、すべての写真の配列、一意のID、説明、およびその他の情報が取得されます。

例として、私はこれを行いませんが、事前にこの配列を手で登録し、作業の準備をしました。

 var photoInfo = []; photoInfo[0] = {'id':5478,'name':'  №1','desc':'  №1','link':'1347690631.jpg'}; photoInfo[1] = {'id':4198,'name':'  №2','desc':'  №2','link':'1347691505.jpg'}; photoInfo[2] = {'id':7596,'name':'  №3','desc':'  №3','link':'1347691550.jpg'}; photoInfo[3] = {'id':98637,'name':'  №4','desc':'  №4','link':'1347691521.jpg'};
      
      







これで、ウィンドウを開くと、一意の写真IDに依存し、配列を並べ替え、現在の写真に必要な情報、およびナビゲーション用の前の写真と次の写真のIDを選択します。 並行して、DOMを調べ、現在のコンテンツがDOMに存在するかどうかを確認します。 存在する場合は開き、存在しない場合は新しいブロックを生成してクラウドに挿入します。 ただし、最初に、DOMにクラウドのあるブロックがあるかどうかを確認します。 まだではない場合、これは最初のクラウド発見です-クラウド生成、そしてその中-クラウドコンテンツの親生成。



 /** *  cloudNav()     cloudShow() *         **/ _cloudNav:function (gid) { if (photoInfo) { var num, prev, next, info, len = photoInfo.length; if (len > 0) { for(var i=0; i<len; i++) { if (photoInfo[i].id == gid) { current = i; info = photoInfo[i]; if (len > 1 && (len-1) > i) {next = photoInfo[i+1].id;} if (len > 1 && i > 0) {prev = photoInfo[i-1].id;} num = i+1; } } } return {"len":len,"num":num,"prev":prev,"current":gid,"next":next,"info":info}; } }, /** *  cloudShow()   ,      * gid -      **/ cloudShow:function (gid) { /**   ,     **/ var arrNav = Content._cloudNav(gid); if (arrNav && arrNav.info) { /**       **/ if (arrNav.prev !== undefined) {ContentPointPrev = arrNav.prev;} else {ContentPointPrev = null;} if (arrNav.next !== undefined) {ContentPointNext = arrNav.next;} else {ContentPointNext = null;} /**   ,          -,    **/ if (elemID('body').style.overflowY != 'hidden') { elemID('body').style.overflowX = 'hidden'; elemID('body').style.overflowY = 'hidden'; } /**        -    **/ if (!elemID('cloud')) { /**      "cloud" **/ var box = document.createElement('div'); box.className = 'cloud'; box.id = 'cloud'; elemID('body').appendChild(box); /**    "cloud" -    **/ var cloudbox = document.createElement('div'); cloudbox.className = 'cloud-layer'; cloudbox.id = 'cloud-layer'; elemID('cloud').appendChild(cloudbox); /**    "cloud"     // **/ var navbox = document.createElement('div'); navbox.id = 'cloud-nav'; elemID('cloud').appendChild(navbox); /**       **/ Content.editSiteLayer('cloud-layer'); /**    -        EM    **/ } else { var ems = elemID('cloud').getElementsByTagName('EM') if (ems.length > 0) { for(var i=0; i<ems.length; i++) { ems[i].style.display = 'none'; } } } /**    **/ elemID('cloud-nav').innerHTML = ''; /**        -    **/ if (!elemID('cloudpage_'+gid)) { var contentbox = document.createElement('em'); contentbox.className = 'cloud-contaner'; contentbox.id = 'cloudpage_'+gid; elemID('cloud-layer').appendChild(contentbox); var html = '<div class="cloud-title">'+ '<div class="cloud-name">'+ ' '+arrNav.num+'  '+arrNav.len+ '</div>'+ '<div class="cloud-close" onclick="return Content.cloudClose();"> </div>'+ '</div>'+ '<div class="cloud-body">'+ '<p><img onclick="'+(arrNav.next !== undefined ? 'return Content.cloudShow('+arrNav.next+')' : 'return Content.cloudClose();')+'" src="images/'+arrNav.info.link+'" alt="" /></p>'+ '<div class="more-button" onclick="Content.Slide(this, {point:\'next\', hide:\'   \', show:\'   \'})">'+ '   '+ '</div>'+ '<span style="display:none;">'+ '<p>'+arrNav.info.name+'</p>'+ '<p>'+arrNav.info.desc+'</p>'+ '<p>'+lorem[0]+'</p>'+ '<p>'+lorem[1]+'</p>'+ '<p>'+lorem[0]+'</p>'+ '<p>'+lorem[1]+'</p>'+ '<p>'+lorem[0]+'</p>'+ '<p>'+lorem[1]+'</p>'+ '</span>'+ '</div>'; elemID('cloudpage_'+gid).innerHTML = html; /**        **/ } else { elemID('cloudpage_'+gid).style.display = 'block'; } /**    **/ var navi = '<div class="cloudnavclose" onclick="return Content.cloudClose();"></div>'; if (arrNav.prev !== undefined) {navi+= '<div onclick="return Content.cloudShow('+arrNav.prev+')" class="cloudnavprev"></div>';} if (arrNav.next !== undefined) {navi+= '<div onclick="return Content.cloudShow('+arrNav.next+')" class="cloudnavnext"></div>';} elemID('cloud-nav').innerHTML = navi; /**  ,    **/ ContentShow = true; /**     **/ elemID('cloud').style.display = 'block'; } },
      
      





上記では、「lorem」配列のいくつかの値を使用しました。その中で、ウィンドウが固定されていることを示すためにページを視覚的に長くするために、事前に非常に長いテキストを用意しました。



ウィンドウが開くと、Content.editSiteLayer( 'cloud-layer')メソッドがロックされます。 -前述の方法により、スクロールバーが表示されたときに左右にジャンプするように埋めることなく、クラウドウィンドウをページの中央に配置します。



ウィンドウを閉じるとき、Content.cloudClose()メソッドが使用されます。 ここにあります:

 /**  cloudClose()    **/ cloudClose:function () { /**      **/ elemID('cloud').style.display = 'none'; /**        **/ elemID('body').style.overflowX = 'auto'; elemID('body').style.overflowY = 'auto'; /**      **/ ContentShow = null; }
      
      







そして最後のタスクは、ホットキーを接続することです。 これを行うには、Content.init()メソッドを作成します。このメソッドは、ホットキーを処理し、ページを読み込むときにブラウザーウィンドウのすぐ中央にページを配置します(記事の冒頭で説明した内容)。

 /** *  init()         **/ init:function () { /**      **/ Content.editSiteLayer('layer'); /**      **/ window.onresize = function() { /**      **/ Content.editSiteLayer('layer'); /**   ,    **/ if (ContentShow) { Content.editSiteLayer('cloud-layer'); } }; /**      **/ window.onkeydown = function(event) { /**     **/ if (ContentShow) { /**   **/ event = event || window.event; switch(event.keyCode) { case 27: //  "Escape" Content.cloudClose(); break; case 37: //  " " (    ID   ) if (ContentPointPrev !== null){Content.cloudShow(ContentPointPrev);} break; case 39: //  " " (    ID   ) if (ContentPointNext !== null){Content.cloudShow(ContentPointNext);} break; } } }; }
      
      





このメソッドは、<BODY>タグを閉じる前にページの最後に記述する必要があります。

 <script type="text/javascript" language="javascript">Content.init();</script>
      
      







なぜそうなのか、なぜフォームのbodyタグに付けられないのかと尋ねる人もいます。

<BODY onload = "Content.init();">いずれかのzayuzat構築window.onload()ただし、この場合、ページ全体が最後までロードされるまでオブジェクトは機能しません。 ページに多くの広告がある場合、これはさらに不快です。 また、中央に9pxだけ左に急にジャンプすると、少し面倒になります。



一般的に、私たちは主なタスクに対処しました。 もう一度デモの例



Opera 12.00、Chrome 21以降、IE 8および9、Safari 5.0およびYandex.browser 1.0ブラウザーでテスト済み

残念ながら、Firefoxでテストする方法はありません。



最後まで読んでいただきありがとうございます。

このアーカイブのデモ例から、すべてのCSS、JavaScriptファイル、およびhtmlをダウンロードできます。

アーカイブには2つのJSファイルが含まれます。

page.js-詳細なコメントを含むファイル

js.js-同じファイル、ただしコメントなし



私はあなたのすべての質問に答えるだけでなく、どんな批判にも耳を傾けます。



All Articles