BBC's guide to development
  • General

    • About
    • Tools
    • Git(hub)
    • Showpad
    • Hosting
    • Maintenance
    • Security
    • Go live checklist
  • Front-end development

    • Bundlers
    • CSS/SCSS
    • Javascript
    • Vue
    • PHP
    • Mails
    • Dev Faq
  • Functions
  • Mixins
  • General

    • OOP Structure
  • Component Classes

    • Accordion
    • App
    • Component
    • HighwayApp
    • Popup
    • PNG Sequencer
    • Tab
  • Manager Classes

    • BountListenerMgr
    • Cache
    • Configuration
    • InViewStateMgr
    • Instance Manager
    • Event dispatcher
  • Factories

    • SwiperFactory
  • PDF

    • AssetLoader
    • BasePdfDoc
    • TemplatePdfDoc
    • CustomPdfDoc
  • Utility functions

    • canvas
    • Connection Status
    • css
    • dev
    • placeholder
    • dom
    • fetch
    • json
    • object
    • scroll
    • scrollbar
    • spreadsheets
    • string
    • url
  • General

    • ComponentMgr
    • ThreeJsViewer
  • Components

    • ComponentMgr
    • GltfModel
    • Snappable
    • Socket
    • ThreeJsViewer
    • ThreeJsViewerCamera
  • Loaders

    • ConfigurationSerializer
    • GltfBlockParser
  • Utils

    • CanvasInputAdapter
    • CollisionManager
    • SocketGridExpander
    • blender
    • headless
  • General

    • Troubleshooting
    • Legacy
  • Components

    • AssetBar
    • ConfigGenerator
    • ShowpadApp
  • Managers

    • Assets
    • AppsDb
    • Config
  • Utils

    • Connection Status
    • general
    • showpad-interactive
    • showpad-upload
  • Components

    • Accordion
    • BackButton
    • Breadcrumb
    • ByltButton
    • Hamburger
    • Icon
    • Logo
    • Loader
    • Modal
    • Popup
    • Prompt
    • ProgressBar
    • TextLoader
  • Composables

    • useDebugMode
    • useConnectionStatus
  • Utils

    • dom
    • props
  • General

    • General
    • Tracking
  • Components

    • Accordion
    • ActionButton
    • AssetItem
    • AssetList
    • BackButton
    • ConfigGenButton
    • Logo
    • Media
    • Modal
    • Popup
    • Prompt
    • SPButton
    • SPRouterView
    • SPTrackedRouterLink
    • TextLoader
    • View
  • Composables

    • useConnectionStatus
  • Stores

    • useAppsDbStore
    • useBreadcrumbStore
    • useShowpadAPIStore
    • useShowpadSDKStore
    • useSpConfigStore
    • useSpStore
    • useSpTrackingStore
  • The New Kit

    • General
    • Installation & Usage
    • ACF Blocks
    • PHPCS
    • Functions
    • Vite
    • WP Config
    • Staging Deployment
  • Best Practices

    • Page Structure
    • Fonts/Typography
  • Todo
GitHub
  • General

    • About
    • Tools
    • Git(hub)
    • Showpad
    • Hosting
    • Maintenance
    • Security
    • Go live checklist
  • Front-end development

    • Bundlers
    • CSS/SCSS
    • Javascript
    • Vue
    • PHP
    • Mails
    • Dev Faq
  • Functions
  • Mixins
  • General

    • OOP Structure
  • Component Classes

    • Accordion
    • App
    • Component
    • HighwayApp
    • Popup
    • PNG Sequencer
    • Tab
  • Manager Classes

    • BountListenerMgr
    • Cache
    • Configuration
    • InViewStateMgr
    • Instance Manager
    • Event dispatcher
  • Factories

    • SwiperFactory
  • PDF

    • AssetLoader
    • BasePdfDoc
    • TemplatePdfDoc
    • CustomPdfDoc
  • Utility functions

    • canvas
    • Connection Status
    • css
    • dev
    • placeholder
    • dom
    • fetch
    • json
    • object
    • scroll
    • scrollbar
    • spreadsheets
    • string
    • url
  • General

    • ComponentMgr
    • ThreeJsViewer
  • Components

    • ComponentMgr
    • GltfModel
    • Snappable
    • Socket
    • ThreeJsViewer
    • ThreeJsViewerCamera
  • Loaders

    • ConfigurationSerializer
    • GltfBlockParser
  • Utils

    • CanvasInputAdapter
    • CollisionManager
    • SocketGridExpander
    • blender
    • headless
  • General

    • Troubleshooting
    • Legacy
  • Components

    • AssetBar
    • ConfigGenerator
    • ShowpadApp
  • Managers

    • Assets
    • AppsDb
    • Config
  • Utils

    • Connection Status
    • general
    • showpad-interactive
    • showpad-upload
  • Components

    • Accordion
    • BackButton
    • Breadcrumb
    • ByltButton
    • Hamburger
    • Icon
    • Logo
    • Loader
    • Modal
    • Popup
    • Prompt
    • ProgressBar
    • TextLoader
  • Composables

    • useDebugMode
    • useConnectionStatus
  • Utils

    • dom
    • props
  • General

    • General
    • Tracking
  • Components

    • Accordion
    • ActionButton
    • AssetItem
    • AssetList
    • BackButton
    • ConfigGenButton
    • Logo
    • Media
    • Modal
    • Popup
    • Prompt
    • SPButton
    • SPRouterView
    • SPTrackedRouterLink
    • TextLoader
    • View
  • Composables

    • useConnectionStatus
  • Stores

    • useAppsDbStore
    • useBreadcrumbStore
    • useShowpadAPIStore
    • useShowpadSDKStore
    • useSpConfigStore
    • useSpStore
    • useSpTrackingStore
  • The New Kit

    • General
    • Installation & Usage
    • ACF Blocks
    • PHPCS
    • Functions
    • Vite
    • WP Config
    • Staging Deployment
  • Best Practices

    • Page Structure
    • Fonts/Typography
  • Todo
GitHub
  • Config

Config

import ShowpadConfig, { PARSERS } from '@bbc/front-end-kit/js/showpad/managers/Config';

A class that extends EventDispatcher and adds Showpad-specific config management to facilitate working with Showpad's config.json.

The Config is mainly made provide consistent and easy access to the contents of the config.json of the Showpad applications. There are many ways to access the json data and this is just another one. It aims to be easy to use and extend and to automate, all while keeping things consistent throughout the codebase.

Some of the functionalities

  • Loads the config json automaticall from the Showpad Library
  • Provides quick access to labels, assets, asset folders, asset queries and assets by tag.
  • Has logic to automatically inject config values into the DOM using Data attributes

Getting started

Het config needs to be initialised and loaded in the following way: Make sure Showpad library is loaded or change the promise structure in such a way to make sure it comes after Showpad finished loading the library.

import ShowpadConfig from '@bbc/front-end-kit/js/showpad/managers/Config'

// initialise config
const config = new ShowpadConfig();

// load & inject into the dom
config.load()
    .then(() => {
        return config.applyToDom()
    })
    .then(() => {
        console.log('config loaded & injected')
    })

Access data

Accessing data can be done using the get method or can happen automatically throughout the dom using the data-sp attribute. Both require at leas a dot-notated version of the path it needs to traverse throught the config property tree.

Example

Config.json

{
    "version": 1,
    "labels": {
        "path": {
            "to": {
                "label-field": {
                    "value": "Some value",
                    "description": "Field description"
                }
            }
        }
    },
    "contents": {
        "path": {
            "to": {
                "asset-field": {
                    "type": "asset",
                    "value": null,
                    "description": "Asset field description"
                }
            }
        }
    }
}

There are many ways to read out the data and use it in the projects. Here are some examples:

Using get in javascript

// access the label
config.get('path.to.label-field'); // returns "Some value"

// access the asset
config.get('path.to.asset-field'); // returns the asset object if assigned in Showpad's editor

Apply To Dom

The config can also inject the values directly into the dom using applytodom(). It will query for elements using specific attribute selectors. The value of these attributes will tell the process what value to use and how to apply it to the DOM.

Data attributes

  • data-sp: Contains the object path in string form to inform the class where the information can be found inside config.json. In case of special types, it can contain other types of information aside from path.
  • data-sp-asset: Contains the info about the type of asset that we expect to find and how it should be applied to the dom, when the path actually leads to an asset in the contents property of config.json. When left empty => dump the contents of the object directly into the dom. Values it supports:
    • asset
    • multitype
    • tags — assets from both tags and page-tags result fields
    • asset-tags — assets from the tags result field only
    • page-tags — assets from the page-tags result field only
    • folder
    • query
  • data-sp-require: Contains the object path in string form to decide if the element it is applied on should be shown or hidden depending on the availability of the value on that path in config.json
  • data-sp-value: Injects the config value into the element's data-value attribute instead of its inner HTML.
  • data-sp-attr: Allows to inject the config value in a desired attribute instead of injecting it like normal. When applied to href of an anchor tag, it will try to detect e-mails and phone numbers so they can be prefixed with their correspondig protocols mailto: and tel:
  • data-sp-count: Contains the path to an array or object in config.json. Injects the count (array length or number of object keys) rather than the value itself.
  • data-sp-processed: Is added during injection to show the path it had generated when placeholders were used.

CSS classes

The injection process will add some classes in certain circumstances. These come in handy when

  • --sp-hide: Is applied to an element using data-sp-require when the config value happens to be empty.
  • --sp-missing: Is applied to an element of which the config value happens to be undefined, assuming the value must be missing in the configuration json.

Path not found

During development it is hard to keep the html with data attributes requesting config field values and the actual config json in sync. To anticipate on these very common frustrations, it will track these down and log them in the console inside a collapsed group. This way it does not clutter the logs too much, yet are they still easily accessible.

closed: Missing log closed

partially opened: Missing log closed

fully opened: Missing log closed

Every missing path in the config will show up with the following info:

  • Path found inside the attribute
  • The processed path in case the raw path contained placeholders that needed to be replaced. Won't show up if there are no placeholders
  • The element the path was found on. When hovering over, it will highlight the element in the page.

Examples

A list of examples on how to use these data attributes in your html.

  • [path]: Is the placeholder that indicates the location of the path (passed to _get) to the value the config has to look for in config.json. (ex: path.to.value)
  • [value] is the placeholder that indicates the location of the value that will is injected in the end-result.

Simple label

<div data-sp="[path]"></div>
<div data-sp="[path]">[value]</div>

Simple label without value but with the required attribute

<div 
    data-sp-require 
    data-sp="[path]"></div>
<div data-sp-require data-sp="[path]" class="--sp-hide"></div>

Simple label without value but applied to element that only needs to be toggled

No value rendered when there is a value.

<div data-sp-require="[path]"></div>
<div data-sp-require="[path]" class="--sp-hide"></div>

Simple asset applied to anchor

Works on any asset (image/video/url/page). Only the url to the asset will be used as value Will always add the modal=1 parameter to the query string to force Showpad to open the asset in the build in popup.

<a data-sp="[path]" data-sp-asset="asset"></a>
<a href="[value]?modal=1" data-sp="[path]" data-sp-asset="asset"></a>

Simple asset applied to image

Works on image assets only. Only the url to the asset will be used as value assuming it will lead to a image-like resource.

<img 
    data-sp="[path]" 
    data-sp-asset="asset" />
<img src="[value]" data-sp="[path]" data-sp-asset="asset" />

Simple asset applied to video

Works on image & video assets only. Only the url to the asset will be used as value assuming it will lead to a video/image-like resource.

This type of asset is ideal to provide support for both image and video in 1 go.

Video asset: When pointing to video, a source tag will be added.

<video 
    data-sp="[path]"
    data-sp-asset="asset"></video>
<video 
    data-sp="[path]" 
    data-sp-asset="asset">
    <source type="video/mp4" src="[value]">
</video>

Image asset: When pointing to an image, a poster tag will be added

<video 
    data-sp="[path]" 
    data-sp-asset="asset"></video>
<video poster="[value]" data-sp="[path]" data-sp-asset="asset"></video>

Simple asset applied to a DIV

Works on image assets only. Only the url to the asset will be used as value assuming it will lead to a image-like resource.

<div data-sp="[path]" 
     data-sp-asset="asset"></div>
<div data-sp="[path]" data-sp-asset style="background-image([value])"></div>

Multitype

A multitype field is a higher-level field. It actually manages 3 fields at once: asset, page-asset and url-asset. It expects these fields to be defined under the same property in config.json.

It will loop through the fields searching for one with a value. It will use the first value it comes accross. From that moment it will treat that asset just like any other asset described above. So it can be applied to DIV, A, IMG and VIDEO

In this example the [path] value should described up until multitype-field: path-to-multitype.multitype-field

{
    ...
    contents: {
        path-to-multitype: {
            "multitype-field": {
                "asset": {
                    "type": "asset",
                    "value": null,
                    "description": "Asset button *"
                },
                "page": {
                    "type": "page",
                    "value": null,
                    "description": "Asset button *"
                },
                "url": {
                    "type": "url",
                    "value": null,
                    "description": "Asset button *"
                }
            }
        }
    }
    ...
}
<video 
    data-sp="[path]" 
    data-sp-asset="multitype"></video>
<video poster="[value]" data-sp="[path]"></video>

Tags

A tag-type asset will load any asset by tag. It supports both the ability to load assets by tags defined in the config and the ability to load tags directly using our Showpad Asset Loader behind the scenes. It will inject the assets in the dom using Handlebars and expecting to find a Handlebars template inside the element it is applied on.

<ul 
    data-sp="[path or comma-separated-tags]"
    data-sp-asset="tags">
    
    <script type="text/x-handlebars-template">
        <li>
            <a href="{{applink}}">
                <div class="label">{{name}}</div>
            </a>
        </li>
    </script>
</ul>
<ul 
    data-sp="[path or comma-separated-tags]"
    data-sp-asset="tags">
    
    <li>
        <a href="[link to asset 1]">
            <div class="label">[name of asset 1]</div>
        </a>
    </li>
    <li>
        <a href="[link to asset 2]">
            <div class="label">[name of asset 2]</div>
        </a>
    </li>
    <li>
        <a href="[link to asset 2]">
            <div class="label">[name of asset 2]</div>
        </a>
    </li>


    <script type="text/x-handlebars-template">
        <li>
            <a href="{{applink}}">
                <div class="label">{{name}}</div>
            </a>
        </li>
    </script>
</ul>

Asset-tags

Like tags, but only uses assets from the tags result field — ignoring any page-tags results. Same Handlebars template structure applies.

<ul 
    data-sp="[path]"
    data-sp-asset="asset-tags">
    
    <script type="text/x-handlebars-template">
        <li><a href="{{applink}}"><div class="label">{{name}}</div></a></li>
    </script>
</ul>

Page-tags

Like tags, but only uses assets from the page-tags result field. Same Handlebars template structure applies.

<ul 
    data-sp="[path]"
    data-sp-asset="page-tags">
    
    <script type="text/x-handlebars-template">
        <li><a href="{{applink}}"><div class="label">{{name}}</div></a></li>
    </script>
</ul>

Folder

A folder-type asset will load any asset from a given folder using the our Showpad Asset Loader behind the scenes. It will inject the assets in the dom using Handlebars and expecting to find a Handlebars template inside the element it is applied on.

<ul 
    data-sp="[folder-link]"
    data-sp-asset="folder">
    
    <script type="text/x-handlebars-template">
        <li>
            <a href="{{applink}}">
                <div class="label">{{name}}</div>
            </a>
        </li>
    </script>
</ul>
<ul 
    data-sp="[folder-link]"
    data-sp-asset="folder">
    
    <li>
        <a href="[link to asset 1]">
            <div class="label">[name of asset 1]</div>
        </a>
    </li>
    <li>
        <a href="[link to asset 2]">
            <div class="label">[name of asset 2]</div>
        </a>
    </li>
    <li>
        <a href="[link to asset 2]">
            <div class="label">[name of asset 2]</div>
        </a>
    </li>


    <script type="text/x-handlebars-template">
        <li>
            <a href="{{applink}}">
                <div class="label">{{name}}</div>
            </a>
        </li>
    </script>
</ul>

Query

A query-type asset will load any asset from part of a given filename using the our Showpad Asset Loader behind the scenes. It will inject the assets in the dom using Handlebars and expecting to find a Handlebars template inside the element it is applied on.

<ul 
    data-sp="[filename]"
    data-sp-asset="folder">
    
    <script type="text/x-handlebars-template">
        <li>
            <a href="{{applink}}">
                <div class="label">{{name}}</div>
            </a>
        </li>
    </script>
</ul>
<ul 
    data-sp="[filename]"
    data-sp-asset="folder">
    
    <li>
        <a href="[link to asset 1]">
            <div class="label">[name of asset 1]</div>
        </a>
    </li>
    <li>
        <a href="[link to asset 2]">
            <div class="label">[name of asset 2]</div>
        </a>
    </li>
    <li>
        <a href="[link to asset 2]">
            <div class="label">[name of asset 2]</div>
        </a>
    </li>


    <script type="text/x-handlebars-template">
        <li>
            <a href="{{applink}}">
                <div class="label">{{name}}</div>
            </a>
        </li>
    </script>
</ul>

Placeholders

As writing down config paths repeatedly can become a very tedious task, it is also possible to define placeholders when initialising the configuration. This helps to make paths more dynamic, every placeholder can either be af fixed value or a function that will decide what value should be used based on a few parameters like the element it is requiring, the placeholder structure, ...

Note

The name of the property on which the placeholder value is defined will be used as the key of the placeholder to look for in the requested config paths.

Fixed value

The fixed value will always replace the placeholder with the same string, wherever it appears

import ShowpadConfig from '@bbc/front-end-kit/js/showpad/managers/Config'

const config = new ShowpadConfig({
    placeholders: {
        myCustomPlaceholder: 'this.is.a.placeholder.piece'
    }
})

config.get('first-part.{{ myCustomPlaceholder }}.field');

// Retuns the value on path:
// [labels/contents].first-part.this.is.a.placeholder.piece.field.value

Dynamic value

Sometimes we need a placeholder that is dynamic depending on the context in which the element is located. To achieve this capability it is required to pass a method instead of a fixed value. The method will receive an object with the following properties to help you decide the output based on the context:

  • $el: The element in the dom from which we're processing the value. (when run by applyToDome, not present when using get)
  • placeholder: The placeholder type were processing.
  • path: The path the element contains, may or may not already be partially processed by another dynamic placeholder method
  • `extracts: Contains all the extracted placeholders that can be found in the path of the elment. Uses èxtractPlaceholders behind the scenes to extract the placeholders.
import ShowpadConfig from '@bbc/front-end-kit/js/showpad/managers/Config'

const config = new ShowpadConfig({
    placeholders: {
        part: ({ $el, placeholder, path, extracts }) => {
            if ($el.tagName === 'H1') {
                return 'title'
            }
            return 'text';
        }
    }
})

config.applyToDom();
<!-- will use value on path: [labels/contents].path.to.title.value -->
<div data-sp="path.to.{{ part }}"></div>

<!-- will use value on path: [labels/contents].path.to.text.value -->
<h1 data-sp="path.to.{{ part }}"></div>

API

constructor (args = {})

The constructor method initialises the Config object

Parameters

  • args: The configuration object used by the constructor to initialise the AppsDb in the desired way.
    • config: Provides the instance with an already existing config object. ...Configuration parameters

load ()

Showpad's config is not automatically available on page load. This method provides a quick way of loading the object and letting us know when it is done.

Returns

Returns a Promise that will resolve when Showpad is done loading the config.

get (path, single = false)

Extends the Configuration's get method with some additional logic.

  • Paths can be shortened. labels and contents can be removed as wel as the value property at the end of the path. labels.some.deeply.nested.title.value can be called up with some.deeply.nested.title instead without issue.
    // full paths
    config.get('labels.some.deeply.nested.title.value')
    
    // shortened path
    config.get('some.deeply.nested.title')
  • Paths passed will first check labels. When nothing is found, it will continue looking for the given path in contents
  • Paths to assets will return the assets instead of returning the value on the contents path.
  • If the asset is a url or folder type, it will return the value of the asset's contents value which will be the url of the asset.

getAssetsByTags (path/tags)

Deprecated

Use Assets.getAssetsByTags() instead.

Returns the assets found on either the given path or by loading them using the given tags.

Parameters

  • path or tags: Either 1 single string representing a path/tag or an array containing strings representing the tags.

Return

Returns a Promise that will resolve when the assets are loaded using the Showpad library. The resolved data object will be an Array of Showpad Asset objects.

getAssetsByTagIds (tags)

Returns the assets that contain the given tag id(s) using our Showpad Asset Loader behind the scenes

Warning

This gets the assets from the loaded assets in the config.json

Parameters

  • tagIds: Either 1 single string representing a tag id or an array containing strings representing the tag ids.

Return

Returns an Array of assets found in config.json matching the tag id criteria.

getAssetsInFolder (folder)

Deprecated

Use Assets.getAssetsInFolder() instead.

Returns all the assets found in the given folder link.

Parameters

  • folder: A string representing the location of the folder where the assets are located.

Return

Returns a Promise that resolves with the raw asset data from the Showpad library.

getAssetByQuery (query)

Deprecated

Use Assets.getAssetsByQuery() instead. Note the singular vs plural naming difference (getAssetByQuery here vs getAssetsByQuery on Assets).

Caution

Not a 'query' method using Showpad's query language! Showpad's getAssetsByQuery completes a predefined query with the given string between % making it a search by name!

Parameters

  • query: A string representing part of the asset name to search for.

Return

Returns a Promise that resolves with an array of matching asset objects.

applyToDom ({ $el, preventLabelInject } = {})

Applies the values stored in Showpad's config.json to the DOM by using values of specific data attributes. (Full documentation)

Parameters

  • $el (Element, default document): Scope root — only elements within this element are processed.
  • preventLabelInject (boolean, default false): When true, skips label injection (plain text values). Used internally by ShowpadApp when configGen is active.

Return

Returns a Promise that will resolve when all the config values are applied to the DOM.

typeOfPath (path)

Checks which section of config.json the given path belongs to.

Parameters

  • path (string): Dot-notated config path.

Returns

'label' if the path resolves in labels, 'asset' if it resolves in contents, or null if the path is not found.

Getters & Setters

config

Get/set the raw config object. The setter dispatches config-changed when the value changes.

labels

The labels section of the loaded config object.

contents

The contents section of the loaded config object.

assets

The assets dictionary of the loaded config object (keyed by asset ID).

attributes

The internal ATTRIBUTES map (e.g. { showpad: 'sp', asset: 'sp-asset', … }). Useful for building custom selectors.

placeholders

The active placeholder map used during DOM injection.

Events

EventWhen
loadedAfter load() successfully parses the config
dom-updatedAfter applyToDom() finishes processing all elements
asset-injectedAfter each individual label or asset is injected into an element. Payload: { details: { $el, label } } or { details: { $el, asset } }
config-changedWhen the config setter receives a new value

Todo

  • Revise getAssetsByTags and getAssetsByTagIds so that it is clear how they will be looking up their assets: using the loaded config object or using Showpad library.
    • Suggestion: Make them all use config.json to force us to use our Showpad Asset Loader when it is required to load them from Showpad directly.
    • Suggestion: Make new class ShowpadConfig so by the time that one is created, we don't need to refactor older projects that are already using the older deprecated Config.js class.
  • Maybe separate applyDom into a separate class so it can both be used for this class and our Showpad Asset Loader directly. It would create a good separation of roles (1 uses config, 1 gets assets using Showpad's library) but only 1 way of applying both resources to the dom.
  • injectAssets should auto detect the presense of a HBS template inside the element, like injectHbsAssets so that all forms of config injection support HBS templates out of the box
Edit this page
Last Updated: 4/27/26, 12:56 PM
Contributors: Nicolas Jaenen