Hướng dẫn Drupal 7: Load content nodes vào modal overlay sử dụng AJAX

Hướng dẫn Drupal 7: Load content nodes vào modal overlay sử dụng AJAX

For one of our current projects (Aiko) we are building a site influenced by the Bloomberg L.P., company site, by Frog Design and the website, Pinterest. The design dictates that most of the site content is presented using a dropdown menu approach. Normally, a dropdown functions best when all of the content is already loaded on the page, and just relies on javascript to animate the display and hiding of each dropdown element.  For this design, it is pretty obvious that requiring all of the overlay content to load along with the initial page is excessive for both load times, as well as complicated for the CMS organization and structure.

AJAX to the rescue.  By loading each of the individual content nodes "on demand" we can cut the unnecessary burden of loading everything up front, and only load the content that is actually requested by the visitor.  Now the question becomes... how do we best do this in Drupal 7?

My solution involves the following approach:

  1. Add a class selector to all links that are meant to open in the overlay (class="overlay").
  2. Use jQuery to find all of these links in the document, and attach the click behavior of loading href into the desired overlay element via ajax, animate the effects, and return false to avoid firing the actual link to a separate page.
  3. Normally the link destination would load the entire page all over again within the overlay element, thus creating an infinite nesting problem (as well as breaking the design).  This is avoided by asking drupal to load these special "overlay" designated links in a different html.tpl.php and page.tpl.php so we can control which parts of the surrounding page are loaded into the overlay.  This is done using the theme's template.php preprocess functions and altering the href sent through ajax.
  4. We also want the url to correctly reflect which overlay page is currently open, and allow direct linking to a specific overlay.  This is handled with jQuery/javascript and dynamic updating of the page hashtag.  Additionally, when a page is first loaded an existing hash is parsed to determine what to display immediately.
  5. Lastly, each overlay may contain a slideshow of content.  If so, we also include this additional information in the hash to also allow for direct linking.

The following modules were used to implement this solution:
menu attributes: to add the class designation to selected menu links

CODE

mytheme/template.php
<?php
function mytheme_preprocess_page(&$vars) {
  if ( isset($_GET['overlay']) && $_GET['overlay'] == 'true' ) {
        $vars['theme_hook_suggestions'][] = 'page__overlay';
  }
}
function mytheme_preprocess_html(&$vars) {
  if ( isset($_GET['overlay']) && $_GET['overlay'] == 'true' ) {
        $vars['theme_hook_suggestions'][] = 'html__overlay';
  }
}
?>
mytheme/script.js
// JavaScript Document

jQuery(document).ready(function () {

  // set overlay-wrap to be hidden from view
  jQuery('#overlay-wrap').css('height', '0px');

  // find all overlay links and add overlay functionality
  jQuery('a.overlay').each( function() {
    jQuery(this).click( function() {
      var href=jQuery(this).attr('href');      // page url to load
      var name=jQuery(this).attr('name');      // new page name
      var rel =jQuery(this).attr('rel');       // new page group
      updateHash(name);
      loadPage(href);
      updateActive(href, rel);
      return false; // important to keep the page from loading in a new window
    });
  });

  // If hashtag exists, load the appropriate page and slide on page load.
  if(hash = parseHash()) {
    if(hash['page']) {
      var href = jQuery('a[name="'+hash['page']+'"]').attr('href');
      var rel = jQuery('a[name="'+hash['page']+'"]').attr('rel');
      var slide = hash['slide'];
      loadPage(href, rel, slide);
      updateActive(href, rel);
    }
  }

});

/* UTILITY FUNCTIONS FOR OVERLAY MANAGEMENT */

// function to update which link is active for styling purposes
function updateActive(href, rel) {
  // remove active from all links
  jQuery('a.active').removeClass('active');
  // add active to all links with same destination
  jQuery('a[href= "'+href+'"]').addClass('active');
  // add active to main level link regardless of destination
  jQuery('#main-menu a[name="'+rel+'"]').addClass('active');
}

// function to update the Hash after the content has changed
function updateHash(page, slide) {
  var list = 'page='+page;                     // add page hash
  if (slide) list += '&slide='+slide;          // add slide hash if exists
  window.location.hash = list;                 // update hash
}

// function to load the content via ajax and animate the overlay
function loadPage(href, rel, slide) {
  // fade out current content
  jQuery('#overlay').stop(true,true).fadeTo('fast', 0, function() {
    // determine if overlay is already open, if not animate it immediately
    if (!jQuery('#overlay-wrap').height()) {
      jQuery('#overlay-wrap').stop(true,true).animate({ height: 200 }, 'slow');
    }
/** 
*   NOTE: the additional '?overlay=true' is added to trigger the new 
*   templates in the template.php file
**/
    jQuery('#overlay').load( href+'?overlay=true', function () {
      if (slide) jQuery('#'+slide).click();  // cycle to correct slide
      // animate the height to fit the new content (within callback after load)
      jQuery('#overlay-wrap').stop(true,true).animate({ 
        height: jQuery('#overlay').height()+10 
      }, 'fast', function() { 
        jQuery('#overlay').stop(true,true).fadeTo('fast', 1.0); // fade in
      });
    });
  });
}

// function to extract data from the existing hash
function parseHash() {
  hash = window.location.hash.substring(1);   // load hash string
  if (!hash) return false;                    // return false if no hash
  var varlist= hash.split("&");               // break hash into variables
  for (i=0; i < varlist.length; i++) {        // cycle through variables
    var vars = varlist[i].split("=");         // split variable name from value
    varlist[vars[0]] = vars[1];               // assign variable value to array
                                              // indexed by variable name
  }
  return varlist;                             // return variable array
}

// function to close the overlay
function closePage() {
  jQuery('#overlay').stop(true,true).fadeTo('fast', 0, function() {
    jQuery('#overlay-wrap').stop(true,true).animate({
      height: 0
    }, 'fast', function() {
      jQuery('#overlay').html('');
      jQuery('a.active').removeClass('active');
      window.location.hash = '';
    });
  });
}
mytheme/html--overlay.tpl.php
<div id="overlay-close"></div>
<?php print $page; ?>
<script type="text/javascript">
  // close button
  jQuery('#overlay-close').click(function() { closePage() });
</script>
mytheme/page--overlay.tpl.php
<div class="overlay-content">
  <?php print render($page['content']); ?>
</div>
mytheme/page.tpl.php (add this code where you want the modal overlay to be located)
<div id="overlay-wrap"><div id="overlay"></div></div>
Bạn thấy bài viết này như thế nào?: 
Average: 5 (1 vote)
Ảnh của Tommy Tran

Tommy owner Express Magazine

Drupal Developer having 9+ year experience, implementation and having strong knowledge of technical specifications, workflow development. Ability to perform effectively and efficiently in team and individually. Always enthusiastic and interseted to study new technologies

  • Skype ID: tthanhthuy

Tìm kiếm bất động sản

 

Advertisement

 

jobsora

Dich vu khu trung tphcm

Dich vu diet chuot tphcm

Dich vu diet con trung

Quảng Cáo Bài Viết

 
Nguyễn Bành Đức trúng tuyển 15 đại học ở Mỹ

Nguyễn Bành Đức, 18 tuổi 7.5 IELTS, SAT là 1.460/1.600 trúng tuyển 15 đại học ở Mỹ

Nguyễn Bành Đức, 18 tuổi, được 15 đại học ở Mỹ cấp học bổng trị giá từ 650 triệu đồng đến gần 5 tỷ đồng cho khóa trọn gói 4 năm.

Hướng dẫn mở rộng để thêm field vào entity / node display trong Drupal 7

I had a case recently, where I needed to add custom data to the node display and wanted this data to behave like a field, however the data itself didn't belong to a field.

How to Recover your Lost or Stolen Digital Camera

How to Recover your Lost or Stolen Digital Camera

Lost your favorite Digital camera, don’t worry now you can easily track your lost digital camera with Stolen Camera Finder website.

Công ty diệt chuột T&C

 

Diet con trung