<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xml:base="https://fourfightingfoxes.com"  xmlns:dc="http://purl.org/dc/elements/1.1/">
<channel>
 <title>fourfightingfoxes - code</title>
 <link>https://fourfightingfoxes.com/blog/code</link>
 <description></description>
 <language>en</language>
<item>
 <title>Drupal 7: Load content nodes into a modal overlay using AJAX</title>
 <link>https://fourfightingfoxes.com/blog/drupal-7-load-content-nodes-into-a-modal-overlay-using-ajax</link>
 <description>&lt;div class=&quot;field field-name-body field-type-text-with-summary field-label-hidden&quot;&gt;&lt;div class=&quot;field-items&quot;&gt;&lt;div class=&quot;field-item even&quot; property=&quot;content:encoded&quot;&gt;&lt;p&gt;For one of our current projects (&lt;a href=&quot;http://www.aikoagency.com&quot; target=&quot;_blank&quot;&gt;Aiko&lt;/a&gt;)&amp;nbsp;we are building a site influenced by the &lt;a href=&quot;http://www.bloomberg.com/company&quot; target=&quot;_blank&quot;&gt;Bloomberg L.P.&lt;/a&gt;, company site, by Frog Design and the website, &lt;a href=&quot;http://pinterest.com/&quot; target=&quot;_blank&quot;&gt;Pinterest&lt;/a&gt;. 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. &amp;nbsp;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.&lt;/p&gt;
&lt;p&gt;AJAX to the rescue. &amp;nbsp;By loading each of the individual content nodes &quot;on demand&quot; we can cut the unnecessary burden of&amp;nbsp;loading everything up front, and only load the content that is actually requested by the visitor. &amp;nbsp;Now the question becomes... how do we best do this in Drupal 7?&lt;/p&gt;
&lt;p&gt;My solution involves the following approach:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Add a class selector to all links that are meant to open in the overlay (class=&quot;overlay&quot;).&lt;/li&gt;
&lt;li&gt;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.&lt;/li&gt;
&lt;li&gt;Normally&amp;nbsp;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). &amp;nbsp;This is avoided by asking drupal to load these special &quot;overlay&quot; 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. &amp;nbsp;This is done using the theme&#039;s template.php preprocess functions and altering the href sent through ajax.&lt;/li&gt;
&lt;li&gt;We also want the url to correctly reflect which overlay page is currently open, and allow direct linking to a specific overlay. &amp;nbsp;This is handled with jQuery/javascript and dynamic updating of the page hashtag. &amp;nbsp;Additionally, when a page is first loaded an existing hash is parsed to determine what to display immediately.&lt;/li&gt;
&lt;li&gt;Lastly, each overlay may contain a slideshow of content. &amp;nbsp;If so, we also include this additional information in the hash to also allow for direct linking.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;The following modules were used to implement this solution:&lt;br /&gt;
&lt;a href=&quot;http://drupal.org/project/menu_attributes&quot; target=&quot;_blank&quot;&gt;menu attributes&lt;/a&gt;: to add the class designation to selected menu links&lt;/p&gt;
&lt;h3&gt;CODE&lt;/h3&gt;
&lt;div&gt;mytheme/template.php&lt;/div&gt;
&lt;pre&gt;&amp;lt;?php
function mytheme_preprocess_page(&amp;amp;$vars) {
&amp;nbsp; if ( isset($_GET[&#039;overlay&#039;]) &amp;amp;&amp;amp; $_GET[&#039;overlay&#039;] == &#039;true&#039; ) {
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; $vars[&#039;theme_hook_suggestions&#039;][] = &#039;page__overlay&#039;;
&amp;nbsp; }
}
function mytheme_preprocess_html(&amp;amp;$vars) {
&amp;nbsp; if ( isset($_GET[&#039;overlay&#039;]) &amp;amp;&amp;amp; $_GET[&#039;overlay&#039;] == &#039;true&#039; ) {
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; $vars[&#039;theme_hook_suggestions&#039;][] = &#039;html__overlay&#039;;
&amp;nbsp; }
}
?&amp;gt;&lt;/pre&gt;
&lt;div&gt;mytheme/script.js&lt;/div&gt;
&lt;pre&gt;// JavaScript Document

jQuery(document).ready(function () {

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

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

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

});

/* UTILITY FUNCTIONS FOR OVERLAY MANAGEMENT */

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

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

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

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

// function to close the overlay
function closePage() {
  jQuery(&#039;#overlay&#039;).stop(true,true).fadeTo(&#039;fast&#039;, 0, function() {
&amp;nbsp;   jQuery(&#039;#overlay-wrap&#039;).stop(true,true).animate({
      height: 0
    }, &#039;fast&#039;, function() {
      jQuery(&#039;#overlay&#039;).html(&#039;&#039;);
&amp;nbsp;&amp;nbsp;    jQuery(&#039;a.active&#039;).removeClass(&#039;active&#039;);
&amp;nbsp;&amp;nbsp;    window.location.hash = &#039;&#039;;
&amp;nbsp;&amp;nbsp;  });
  });
}&lt;/pre&gt;
&lt;div&gt;mytheme/html--overlay.tpl.php&lt;/div&gt;
&lt;pre&gt;&amp;lt;div id=&quot;overlay-close&quot;&amp;gt;&amp;lt;/div&amp;gt;
&amp;lt;?php print $page; ?&amp;gt;
&amp;lt;script type=&quot;text/javascript&quot;&amp;gt;
  // close button
  jQuery(&#039;#overlay-close&#039;).click(function() { closePage() });
&amp;lt;/script&amp;gt;&lt;/pre&gt;
&lt;div&gt;mytheme/page--overlay.tpl.php&lt;/div&gt;
&lt;pre&gt;&amp;lt;div class=&quot;overlay-content&quot;&amp;gt;
  &amp;lt;?php print render($page[&#039;content&#039;]); ?&amp;gt;
&amp;lt;/div&amp;gt;&lt;/pre&gt;
&lt;div&gt;mytheme/page.tpl.php (add this code where you want the modal overlay to be located)&lt;/div&gt;
&lt;pre&gt;&amp;lt;div id=&quot;overlay-wrap&quot;&amp;gt;&amp;lt;div id=&quot;overlay&quot;&amp;gt;&amp;lt;/div&amp;gt;&amp;lt;/div&amp;gt;&lt;/pre&gt;
&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;a href=&quot;/blog/drupal-solutions&quot; typeof=&quot;skos:Concept&quot; property=&quot;rdfs:label skos:prefLabel&quot; datatype=&quot;&quot;&gt;Drupal Solutions&lt;/a&gt;&lt;span class=&quot;tag&quot;&gt;&lt;a href=&quot;/blog/ajax&quot; typeof=&quot;skos:Concept&quot; property=&quot;rdfs:label skos:prefLabel&quot; datatype=&quot;&quot;&gt;ajax&lt;/a&gt;&lt;/span&gt;&lt;span class=&quot;tag&quot;&gt;&lt;a href=&quot;/blog/code&quot; typeof=&quot;skos:Concept&quot; property=&quot;rdfs:label skos:prefLabel&quot; datatype=&quot;&quot;&gt;code&lt;/a&gt;&lt;/span&gt;</description>
 <pubDate>Thu, 19 Jan 2012 17:01:44 +0000</pubDate>
 <dc:creator>jason</dc:creator>
 <guid isPermaLink="false">58 at https://fourfightingfoxes.com</guid>
 <comments>https://fourfightingfoxes.com/blog/drupal-7-load-content-nodes-into-a-modal-overlay-using-ajax#comments</comments>
</item>
</channel>
</rss>
