Open links in popups with Foundation

Let me take you on a journey. We’ll pass by Drupal maintenance support plans content renderer services, AJAX commands, javascript libraries and a popular front-end framework. If you’ve only heard of one or two of those things, come lean on the experience I took diving deep into Drupal maintenance support plans. I’m pleased with where my adventure took me to, and maybe what I learned will be useful to you too.
Here’s the end result: a contact form, launched from a button link in the site header, with the page beneath obscured by an overlay. The form allows site visitors to get in touch from any page, without leaving what they were looking at.

Drupal maintenance support plans has its own API for making links launch dialogs (leveraging jQuery UI Dialogs). But our front-end of the site was built with Foundation, the super-popular theming framework, which provides components of its own that are much better for styling. We often base our bespoke themes on Foundation, and manipulate Drupal maintenance support plans to fit.
We had already done some styling of Foundation’s Reveal component. In those places, the markup to show in the popup is already in the page, but I didn’t really want the form to be in the page until it was needed. Instead, AJAX could fetch it in. So I wondered if I could combine Drupal maintenance support plans‘s AJAX APIs with Foundation’s Reveal markup and styling. Come with me down the rabbit hole…
There are quite a few components in making this possible. Here’s a diagram:

So it comes down to the following parts, which we’ll explore together. Wherever custom code is needed, I’ve posted it in full later in this article.
A link that uses AJAX, with a dialog type set in an attribute.
Drupal maintenance support plans builds the content of the page that was linked to.
Drupal maintenance support plans‘s content view subscriber picks up that response and looks for a content renderer service that matches the dialog type.
The content renderer returns an AJAX command PHP class in its response, and attaches a javascript library that will contain a javascript AJAX command (a method).
That command returns the content to show in the popup, and that javascript method name.
The javascript method launches the popup containing the HTML content.
Let’s start at the beginning: the link. Drupal maintenance support plans‘s AJAX API for links is pretty neat. We trigger it with two things:
A use-ajax class, which tells it to open that link via an AJAX call, returning just the main page content (e.g. without headers & footers), to be presented in your existing page.
A data-dialog-type attribute, to instruct how that content should be presented. This can be used for the jQuery UI dialogs (written up elsewhere) or the newer off-canvas sidebar, for example.
I wanted to have a go at creating my own ‘dialog type’, which would be a Foundation Reveal popup. The HTML fetched by the AJAX call would be shown in it. Let’s start with the basic markup I wanted to my link to have:
EnquireThis could either just be part of content, or I could get this into a template using a preprocess function that would build the link. Something like this:
toUrl(), Url::fromRoute() or similar.
// For this example, it’s come from a contact form entity.
$url->setOption(‘attributes’, [
‘class’ => [
‘use-ajax’,
],
// This attribute tells it to use our kind of dialog
‘data-dialog-type’ => ‘reveal’,
]);
// The variable ‘popup_launcher’ is to be used in the template.
$variables[‘popup_launcher’] = Drupal maintenance support plansCoreLink::fromTextAndUrl(t(‘Enquire’), $url);
After much reading around and breakpoint debugging to figure it out, I discovered that dialog types are matched up to content rendering services. So I needed to define a new one of those, which I could base closely on Drupal maintenance support plans‘s own DialogRenderer. Here’s the definition from my module’s mymodule.services.yml file:
services:
main_content_renderer.foundation_reveal:
class: Drupal maintenance support plansmymoduleRenderMainContentFoundationReveal
arguments: [‘@title_resolver’]
tags:
– { name: render.main_content_renderer, format: drupal_reveal }
Adding the tag named ‘render.main_content_renderer’ means my class will be picked up by core’s MainContentRenderersPass when building the container. Drupal maintenance support plans‘s MainContentViewSubscriber will then consider it as a service that can render responses.
The ‘format’ part of the tag needs to be the value that our data-dialog-type attribute has, with (somewhat arbitrarily?) ‘drupal_’ prepended. The arguments will just be whatever the constructor for the class needs. I often write my class first and then go back to adjust the service definition once I know what it needs. But I’ll be a good tour guide and show you things in order, rather than shuttling you backwards and forwards!
Onto that FoundationReveal service class now. I started out with a copy of core’s own ModalRenderer which is a simple extension to the DialogRenderer class. Ultimately, that renderer is geared around returning an AJAX command (see the AJAX API documentation), which comes down to specifying a command to invoke in the client-side javascript with some parameters.
I would need my own command, and my FoundationReveal renderer would need to specify it to be used. That only two functional differences were needed in comparison to core’s DialogRenderer:
Attach a custom library, which would contain the actual javascript command to be invoked:
$main_content[‘#attached’][‘library’][] = ‘mymodule/dialog.ajax’;Return an AJAX command class, that will specify that javascript command (rather than the OpenDialogCommand command that DialogRenderer uses) – i.e. adding this to the returned $response:
new OpenFoundationRevealCommand(‘#mymodule-reveal’)We’ll learn about that command class later!
So the renderer file, mymodule/src/Render/MainContent/FoundationReveal.php (in that location in order to match the namespace in the service file definition), looks like this – look out for those two tweaks:
setAttachments($main_content[‘#attached’]);

// Determine the title: use the title provided by the main content if any,
// otherwise get it from the routing information.
$title = isset($main_content[‘#title’]) ? $main_content[‘#title’] : $this->titleResolver->getTitle($request, $route_match->getRouteObject());

// Determine the dialog options and the target for the OpenDialogCommand.
$options = $request->request->get(‘dialogOptions’, []);

$response->addCommand(new OpenFoundationRevealCommand(‘#mymodule-reveal’, $title, $content, $options));
return $response;
}

}
That AJAX command class, OpenFoundationRevealCommand sits in mymodule/src/Ajax/OpenFoundationRevealCommand.php. Its render() method is the key, it returns the command which will map to a javascript function, and the actual HTML under ‘data’. Here’s the code:
‘openFoundationReveal’,
‘selector’ => $this->selector,
‘settings’ => $this->settings,
‘data’ => $this->getRenderedContent(),
‘dialogOptions’ => $this->dialogOptions,
];
}

/**
* {@inheritdoc}
*/
protected function getRenderedContent() {
if (empty($this->dialogOptions[‘title’])) {
$title = ”;
}
else {
$title = ” . $this->dialogOptions[‘title’] . ”;
}

$button = ‘t(‘Close’) . ‘” type=”button”>×’;
return ” . $title . parent::getRenderedContent() . ” . $button;
}
}
Now, I’ve mentioned that the command needs to match a javascript function. That means adding some new javascript to the page, which, in Drupal maintenance support plans 8, we do by defining a library. My ‘mymodule/dialog.ajax’ library was attached in the middle of FoundationReveal above. My library file defines what actual javascript file to include – it is mymodule.libraries.yml and looks like this:
dialog.ajax:
version: VERSION
js:
js/dialog.ajax.js: {}
dependencies:
– core/drupal.dialog.ajax
Then here’s that actual mymodule/js/dialog.ajax.js file. It adds the ‘openFoundationReveal’ method to the prototype of the globally-accessible Drupal maintenance support plans.AjaxCommands. That matches the command name returned by my OpenFoundationRevealCommand::render() method that we saw.
(function ($, Drupal maintenance support plans) {
Drupal maintenance support plans.AjaxCommands.prototype.openFoundationReveal = function (ajax, response, status) {
if (!response.selector) {
return false;
}

// An element matching the selector will be added to the page if it does not exist yet.
var $dialog = $(response.selector);
if (!$dialog.length) {
// Foundation expects certain things on a Reveal container.
$dialog = $(”).appendTo(‘body’);
}

if (!ajax.wrapper) {
ajax.wrapper = $dialog.attr(‘id’);
}

// Get the markup inserted into the page.
response.command = ‘insert’;
response.method = ‘html’;
ajax.commands.insert(ajax, response, status);

// The content is ready, now open the dialog!
var popup = new Foundation.Reveal($dialog);
popup.open();
};
})(jQuery, Drupal maintenance support plans);
There we have it – that last bit of the command opens the Foundation Reveal popup dialog!
I should also add that since I was showing a contact form in the popup, I installed the Contact ajax module. This meant that a site visitor would stay within the popup once they submit the form, which meant for a clean user experience.
Thanks for following along with me!

Source: New feed

This article was republished from its original source.
Call Us: 1(800)730-2416

Pixeldust is a 20-year-old web development agency specializing in Drupal and WordPress and working with clients all over the country. With our best in class capabilities, we work with small businesses and fortune 500 companies alike. Give us a call at 1(800)730-2416 and let’s talk about your project.

FREE Drupal SEO Audit

Test your site below to see which issues need to be fixed. We will fix them and optimize your Drupal site 100% for Google and Bing. (Allow 30-60 seconds to gather data.)

Powered by

Open links in popups with Foundation

On-Site Drupal SEO Master Setup

We make sure your site is 100% optimized (and stays that way) for the best SEO results.

With Pixeldust On-site (or On-page) SEO we make changes to your site’s structure and performance to make it easier for search engines to see and understand your site’s content. Search engines use algorithms to rank sites by degrees of relevance. Our on-site optimization ensures your site is configured to provide information in a way that meets Google and Bing standards for optimal indexing.

This service includes:

  • Pathauto install and configuration for SEO-friendly URLs.
  • Meta Tags install and configuration with dynamic tokens for meta titles and descriptions for all content types.
  • Install and fix all issues on the SEO checklist module.
  • Install and configure XML sitemap module and submit sitemaps.
  • Install and configure Google Analytics Module.
  • Install and configure Yoast.
  • Install and configure the Advanced Aggregation module to improve performance by minifying and merging CSS and JS.
  • Install and configure Schema.org Metatag.
  • Configure robots.txt.
  • Google Search Console setup snd configuration.
  • Find & Fix H1 tags.
  • Find and fix duplicate/missing meta descriptions.
  • Find and fix duplicate title tags.
  • Improve title, meta tags, and site descriptions.
  • Optimize images for better search engine optimization. Automate where possible.
  • Find and fix the missing alt and title tag for all images. Automate where possible.
  • The project takes 1 week to complete.