Help Center

Tutorial 2: Lightbox

Difficulty: Intermediate

In the Hello World! tutorial a very basic plugin was created. This tutorial aims to create a more complex plugin: a custom lightbox. In creating the plugin we will touch on typical subjects that arise when developing custom plugins.


Introduction

In this tutorial we will create an Interaction Type plugin for creating an interaction Dialogue for a lightbox on a page in the BlueConic Client (the backend). The content displayed in the lightbox can be edited to suit your needs.

The Dialogue will show visitors to the website (the frontend) a lightbox with the configured content.


File structure

This plugin requires a number of files that are structured as in the schematic directory overview below:

mylightbox/
  +-- jquery/
  |     +-- jquery-1.11.2.min.js
  +-- fancybox/
  |     +-- blank.gif
  |     +-- [...]
  |     +-- jquery.fancybox.pack.js
  +-- mylightbox.js
  +-- mylightbox.xml

Although this directory structure looks much more complex than the "Hello World!" example, it builds on the same structure:

  • "mylightbox.xml" is the XML definition file.
  • "mylightbox.js" is the main JavaScript file.

Additionally:

  • To display our lightbox we use jQuery and its plugin Fancybox. The "jquery" and "fancybox" directories contain the third-party library files that we need to make our lightbox work.

The files can be downloaded here: mylightbox-1.0.0.zip

Relevant files are explained in more detail in the following sections.


XML definition file

<?xml version="1.0" encoding="UTF-8"?>
<plugin>
  <id>mylightbox</id>
  <version>1.0.0</version>
  <type>action</type>
  <name>
    <label locale="en_US">My Lightbox</label>
    <label locale="nl_NL">Mijn Lightbox</label>
  </name>
  <description>
    <label locale="en_US">A 'My Lightbox' dialogue 
allows you to display entered content or external
content in a lightbox on a web-based channel.</label> </description> <!-- frontend specific properties --> <frontend> <script>mylightbox.js</script> <positiontype>overlay</positiontype> <libraries> <library>/jquery/jquery-1.11.2.min.js</library> <library>/fancybox/jquery.fancybox.pack.js</library> </libraries> </frontend> <!-- backend specific properties --> <backend> <view>channel</view> <parameters> <parameter> <id>content</id> <type>html</type> </parameter> </parameters> </backend> </plugin>

This XML definition file contains the following instructions:

  • The <id> is the unique identifier string that allows BlueConic to distinguish this plugin from other plugins.
  • The <version> contains a version number. Once you have installed a plugin in BlueConic, you can only update to higher version numbers. So, if you install version "1.0.0" of this plugin, you can update to version "1.0.1" or version "2.27.0". But you cannot install version "1.0.0" again - unless you delete the existing plugin first. However, remember that deleting a plugin will also delete all dialogues based on that plugin!
  • The <type> tells BlueConic that this plugin contains a dialogue that performs some visual action.
  • The <label> is a friendly name for the plugin. The locale indicates for which of the editing languages the friendly name is. Currently only "en_US" and "nl_NL" are supported.
  • The <description> provides a description of what the plugin does.

Above are the general instructions. There are also instructions specifically for the <frontend>:

  • The <script> tag defines the JavaScript file that will be executed to implement the inner workings of the plugin, in this case "mylightbox.js".
  • The <positiontype> tag defines what kind of positioning the plugin uses. Since our lightbox does not require a position, but is shown in a layer hovering above the page, we use the value "overlay".
  • The <libraries> tag contains the paths to external JavaScript libraries that need to be loaded for this plugin to work. In our case we want jQuery and Fancybox to be loaded, so we specify the paths to them, using "/" to refer to the root directory of the plugin. So the <library> paths become: "/jquery/jquery-1.11.2.min.js" and "/fancybox/jquery.fancybox.pack.js". If you want to learn more about dependencies, see BCGD001 - Use declared dependencies to load the required JavaScript libraries (JQuery, for example).

There are also instructions specifically for the <backend>:

  • The <view> tag tells BlueConic that the backend should use the "channel" view (i.e. display the website inline) when editing the dialogue.
  • The <parameters> tag contains the definitions of parameters that the user can configure in the UI. In this case we define a <parameter> with the <id> "content" of the <type> "html", because we want to enable the user to type in the lightbox editor and store the edits.

JavaScript file

mylightbox.js

var InteractionTypeImpl = InteractionType.extend( {

  // Called every time a new interaction dialogue of this type is created.
  init: function(blueConicClient, context) {
    this.blueConicClient = blueConicClient;
    this.context = context;

    // Url for this interactiontype
    var interactionTypeId = context.getInteractionTypeId();
    var baseUrl = blueConicClient.getBaseURL(interactionTypeId);

    // Load the CSS for the fancybox jQuery plugin
    var fancyboxCSS = baseUrl + 'fancybox/jquery.fancybox.css';
    blueConicClient.util.loadCSS(fancyboxCSS);

    // Retrieve the content
    var params = this.context.getParameters();
    var html = params.content ? params.content[0] : params.content;

    if (typeof html === 'undefined') {
      // Make sure the variable is defined
      html = ' ';
    }

    // Create a HTML fragment for the HTML we need to add to the DOM
    this.htmlFragment = this.createElement(html);
  },

  // Called when an interaction dialogue based on this type is executed.
  onLoad: function() {
    this.showLightbox();
  },

  // The work horse of our plugin
  showLightbox: function() {
    var content = ' ';
    var effect = 'elastic';
    var width = 200;
    var height = 150;

    if (this.htmlFragment) {
      content = this.htmlFragment.innerHTML;
    }

    var settings = {
      'autoDimensions': false,
      'type': 'inline',
      'content': content,
      'width': width,
      'height': height,
      'transitionIn': effect,
      'transitionOut': effect
    };

    // Create the lightbox
    this.jQuery.fancybox(settings);

    if (this.blueConicClient.isInEditMode()) {
      // The inside of the lightbox is editable
      this.blueConicClient.setEditableNode('.fancybox-inner', {
          colorScheme: 'light',
          positionName: 'My Lightbox'
      });
    }
  },

  // Utility function to create an element inside a div
  createElement: function(html) {
    var fragment;

    if (!html) {
      return null;
    }

    try {
      fragment = document.createElement('div');
      fragment.innerHTML = html;
    } catch(error) {
      return null;
    }

    return fragment;
  }
});

This JavaScript defines four functions:

The JavaScript is discussed in more detail below.

var InteractionTypeImpl = InteractionType.extend({
Like every interaction dialogue plugin, our plugin extends the default BlueConic InteractionType. The function extend() takes an object with function definitions as argument. The defined functions will overrule the standard functions of the InteractionType. For our lightbox example we overrule two API functions (init(), onLoad()) and add our own functions function showLightbox() andcreateElement(). We will go into more details for each of these functions below.
init: function(blueConicClient, context) {

This line overrules the API function init(blueConicClient, interactionContext). The function is called every time a new interaction dialogue of this type is created. We start by storing the two parameters blueConicClient and interactionContext, because we will need them to retrieve parameter values when showing the actual lightbox:

    this.blueConicClient = blueConicClient;
    this.context = context;

The lightbox is based on the jQuery plugin Fancybox, which needs its own style sheet information to be loaded on the web page. This information is stored in the directory structure of our plugin, in the file "jquery.fancybox.css". To load the CSS information we first obtain the id for our interactionType using getInteractionTypeId(). With this id, we can get the base URL for our deployed plugin using getBaseURL(interactionTypeId).

We then append the path of the Fancybox CSS file to the base URL to get the full URL from which we can load the CSS using util.loadCSS(stylesheet):

    // Url for this interactiontype
    var interactionTypeId = context.getInteractionTypeId();
    var baseUrl = blueConicClient.getBaseURL(interactionTypeId);

    // Load the CSS for the fancybox jQuery plugin
    var fancyboxCSS = baseUrl + 'fancybox/jquery.fancybox.css';
    blueConicClient.util.loadCSS(fancyboxCSS);

Note: Fancybox also needs a JavaScript library, which is why we defined it as <library> in the XML definition file. This will make BlueConic load the library automatically.

To finish the initialization, we make sure that we have a HTML fragment to display. We retrieve the content using the function getParameters(). In a new Dialogue the content will be undefined, so we check for this and make sure the variable html is defined. Finally we create a HTML fragment based on the content for later use when we actually want to display the lightbox. The this.htmlFragment will hold onto the content for us.

    // Retrieve the content
    var params = this.context.getParameters();
    var html = params.content ? params.content[0] : params.content;

    if (typeof html === 'undefined') {
      // Make sure the variable is defined
    	html = ' ';
    }

    // Create a HTML fragment for the HTML we need to add to the DOM
    this.htmlFragment = this.createElement(html);
onLoad: function() {
Nothing exciting about this function; we overrule the API function onLoad(), which is called when the plugin is executed for an interaction of a dialogue. The only thing we do here is make a function call to show the lightbox.
  onLoad: function() {
    this.showLightbox();
  },
showLightbox: function() {

This function is in charge of displaying the lightbox. To do so, it must first gather the settings and then it can create the lightbox.

First, we define some static values:

  showLightbox: function() {
    var content = ' ';
    var effect = 'elastic';
    var width = 200;
    var height = 150;

We then apply some checks, because the lightbox will not display if the content is empty. More importantly, we prefer to use our private HTML fragment storage for the content value. As a final sanity check, the content cannot be empty or fancybox will not show a lightbox at all:

 if (this.htmlFragment) {
   content = this.htmlFragment.innerHTML;
 }

if (typeof content === 'undefined' || content === null || content === '') {
  content = ' ';
}

What follows is fancybox specific code; a function beforeLoad() to force the lightbox to listen to resizes (just setting the width and height does not seem to be enough) and settings to initialize the lightbox. With everything in place, we create the lightbox:

    // Function to adjust the width and height of the fancybox
    var beforeLoad = function() {
      this.width = width;
      this.height = height;
      this.minWidth = width;
      this.minHeight = height;
      this.maxWidth = width;
      this.maxHeight = height;
    };

    var settings = {
      'autoDimensions': false,
      'type': 'inline',
      'content': content,
      'width': width,
      'height': height,
      'transitionIn': effect,
      'transitionOut': effect,
      'beforeShow': beforeLoad,
      'beforeLoad': beforeLoad
    };

    // Create the lightbox
    this.jQuery.fancybox(settings);

Now that the lightbox is drawn, we can point out which HTML node can be edited using the function setEditableNode(domElement, options). This is only relevant if the Dialogue is being edited, so we use the function isInEditMode() to verify if this is the case:

    if (this.blueConicClient.isInEditMode()) {
      // The inside of the lightbox is editable
      this.blueConicClient.setEditableNode('.fancybox-inner', {
          colorScheme: 'light',
          positionName: 'My Lightbox'
      });
    }

Packaging the plugin

Package the plugin by creating a Zip file with the file structure laid out above. Make sure the files "mylightbox.xml" and "mylightbox.js" are in the root of the Zip file.

You can install the packaged plugin in BlueConic and create a new dialogue that uses the "My Lightbox" plugin. See the Hello World! tutorial for the details on how to do this. 


Summary

In this tutorial you learned how to create a custom BlueConic plugin for an editable lightbox.

The next tutorial expands this plugin by adding parameters to it.

To learn more about BlueConic Plugins, see the Getting Started page for an overview of available tutorials.

 

Was this article helpful?
0 out of 0 found this helpful