Tutorial 3: Lightbox v2

Difficulty: Intermediate

In the Lightbox tutorial we created a custom plugin for a lightbox. In this tutorial we will expand on that by adding parameters to control the appearance of the lightbox.


Introduction

Now that we created an Interaction Type plugin that allows a marketer to create a Dialogue for a lightbox on a page, we will build on that to allow editing some lightbox properties. With these properties the lightbox can be shaped by width, height and an entrance effect selectable by pulldown. This way the marketer can not only determine the content, but also the appearance of the lightbox.

The Dialogue will show the visitor of the website (the frontend) a lightbox with the configured content and appearance.


File structure

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

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

This directory structure is essentially the same as the "My Lightbox" tutorial. The changes are:

  • "mylightbox.xml" is modified to define parameters
  • "mylightbox.js" is modified to use the parameters

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

The changes are explained in more detail in the following sections.


XML definition file

<?xml version="1.0" encoding="UTF-8"?>
<plugin>
  <id>mylightbox</id>
  <version>2.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' interaction 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.7.2.min.js</library>
      <library>/fancybox/jquery.fancybox.pack.js</library>
    </libraries>
  </frontend>

  <!-- backend specific properties -->
  <backend>
    <!-- Show the plugin in channel view when editing a Dialogue -->
    <view>channel</view>

    <parameters>
      <parameter>
        <id>content</id>
        <name>
          <label locale="en_US">Content</label>
          <label locale="nl_NL">Inhoud</label>
        </name>
        <type>html</type>
      </parameter>

      <parameter>
        <id>width</id>
        <name>
          <label locale="en_US">Width</label>
          <label locale="nl_NL">Breedte</label>
        </name>
        <type>number</type>
      </parameter>

      <parameter>
        <id>height</id>
        <name>
          <label locale="en_US">Height</label>
          <label locale="nl_NL">Hoogte</label>
        </name>
        <type>number</type>
      </parameter>

      <parameter>
        <id>effect</id>
        <name>
          <label locale="en_US">Effect</label>
          <label locale="nl_NL">Effect</label>
        </name>
        <description>
          <label locale="en_US">Choose the effect with which the lightbox should appear and disappear.</label>
          <label locale="nl_NL">Selecteer het effect waarmee de lightbox verschijnt en verdwijnt.</label>
        </description>
        <type>string</type>
      </parameter>
    </parameters>
  </backend>
</plugin>

This XML definition file contains the following updated instructions:

  • The <version> has been bumped to "2.0.0".

The instructions specifically for the <backend> have changed as well:

  • The <parameters> tag contains the definitions for the four parameters that shape our lightbox: "content", "width", "height" and "effect". The <parameter> definitions themselves are fairly self explanatory: they all have a unique <id>, a <name> with locale sensitive <label>s and a <type> that defines the type of parameter.

    Several types are available:

    ValueDescription
    boolean The parameter contains a boolean value "true" or "false".
    file The parameter allows a file to be uploaded.
    image The parameter allows an image to be uploaded.
    html If a parameter of the type html exists, it is assumed to be the editable HTML content of the position. This means that the parameter will not automatically get an edit field in the properties widget. Instead it should be edited via the so-called "editable node". By default this is the DOM node indicated by the Position of the Dialogue, however, the default can be overruled withsetEditableNode(). A maximum of one parameter of this type should exist.
    number The parameter contains an integer number. Non-number characters are forbidden.
    string The parameter contains a string of characters. Characters of the UTF-8 character set are allowed, which means that Chinese or Arabic characters are allowed.

By defining the parameters in the XML definition file BlueConic will display editable entries in the "Properties" widget when editing a Dialogue:


JavaScript file

mylightbox.js

var InteractionTypeImpl = InteractionType.extend( {

  // Called every time a new interaction 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 based on this type is executed.
  onUpdate: function() {
    if (this.jQuery('.fancybox-inner').length > 0 && this.htmlFragment) {
      // Update the lightbox content from the editable node
      this.htmlFragment.innerHTML = this.jQuery('.fancybox-inner').html();
    }

    this.showLightbox();
  },

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

  // The work horse of our plugin
  showLightbox: function() {
    var params = this.context.getParameters();
    var content = params.content[0];
    var effect = params.effect[0];
    var width = params.width[0];
    var height = params.height[0];

    if (width === '') {
    	width = 200;
    }

    if (height === '') {
    	height = 200;
    }

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

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

    // 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);

    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 five functions:

  • init(), onUpdate() and onLoad() override JavaScript API functions to tap into BlueConic plugin events.
  • showLightbox() and createElement() are our own functions to display a lightbox.

The JavaScript file has largely been left unchanged from the original. The changes are discussed in detail below.

onUpdate: function() {

This line overrules the API function onUpdate(), which is only called when plugin parameters have been updated while editing the Dialogue in BlueConic. This function is never called on the frontend. This makes the function an ideal spot to redraw the lightbox based on the changed parameters.

Because we are about to redraw the lightbox and its contents, we want to make sure we use the latest contents. It is important to note that the "content" parameter is only updated when the Dialogue is saved. If you edit the content of the lightbox (without saving) and then change the width of the lightbox (again without saving), an update event will be fired, but the content parameter will not have been updated. The lightbox would be redrawn with the previous (unedited) content.

To use the latest contents: before we call the function showLightbox(), we first check if there is content in the lightbox, because this is where the marketer would edit it inline. We use jQuery to find the inner content of the fancybox lightbox and update our HTML fragment with its content.

Note that the reason we can use jQuery is that we defined jquery-1.7.2.min.js as a <library> in the XML definition file. Defining a dependency to a library will make BlueConic inject the library into the Interaction, which is why we use this.jQuery(...) in our code to call it. This means our code can use a different version of the jQuery library than the page, or even other interaction types! For more information on dependencies, see BCGD001 - Use declared dependencies to load the required JavaScript libraries (JQuery, for example).

  onUpdate: function() {
    if (this.jQuery('.fancybox-inner').length > 0 && this.htmlFragment) {
      // Update the lightbox content from the editable node
      this.htmlFragment.innerHTML = this.jQuery('.fancybox-inner').html();
    }

    this.showLightbox();
  },
showLightbox: function() {

Instead of assigning constant values to the lightbox variables, this time we gather the parameter values using getParameters():

  showLightbox: function() {
    var params = this.context.getParameters();
    var content = params.content[0];
    var effect = params.effect[0];
    var width = params.width[0];
    var height = params.height[0];

Parameter values might be empty, so we apply some sanity checks and enforce a default width, height and content when empty. We also add a function beforeLoad to help the lightbox cope with size changes on reloads:

    if (width === '') {
      width = 200;
    }

    if (height === '') {
    	height = 200;
    }

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

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

    // 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
    };

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.

It is best to empty your browser cache and reload the page after updating a plugin to make sure the new JavaScript is actually being used.

If all went as planned, you should be able to modify the appearance of the lightbox.


Summary

In this tutorial you learned how to add parameters to a custom BlueConic plugin and how to use their values from the plugin JavaScript.

If you want to learn more about BlueConic plugins, check the Getting Started page for an overview of available tutorials.