Please click here if you are not redirected within a few seconds.
CMS Media Picker Client › shanebow.com
CMS Media Picker Client

A fundamental requirement of any Content Management System is the ability to include pictures, videos, or any other media in our web pages.

The ShaneBow MediaPicker system allows us to do this with simple reusable code that hides all the ugly details and a intuitive UI.

This post shows the client side usage and coding in a future post we will explore the back end and API.

Requirements

Using the MediaPicker Dialog

Let's say we want to insert an image into a blog post. The image that we want to insert on the page must be on a file server someplace. Consider these possibilities:

Our MediaPickerclass pops up a dialog with Remote and Upload tabs to handle these two possibilities. (There is a third possibility that the file is on somebody else's server: Don't do this! See Avoid Hotlinking in the sidebar)

The dialog also features a search input to filter remote media by title and description.

Media Picker Search Results Remote
Select media on the server from a paged list sorted from most recent to oldest entries.
Media Picker Search Results Search Results
Find uploaded media with title or description containing the search term
Media Picker Search Results Upload
Upload a file from the local machine and give it title, description and attribution.

Coding the MediaPicker

The MediaPicker class is designed to be flexible enough to handle most any use case.

Below, we demonstrate the following use cases:

    const picker = new MediaPicker(selector, options);

Avatar Example

In this example from the timelines project, the event editor allows us to assign an image to each event. To set the image, just click on it and choose either a local or remote image.

It uses the default settings and so it painless to use.

As with all the images on this page, you can click this one to enlarge it — which you want to do to get a better look at my twin boys! or go check out the rendered page on sirijanda.com!!


Markup

We just need a <div> with a single <img> inside.

The markup shows that after the MediaPicker has been invoked, the src attribute is automatically updated to the new URL and the image is assigned an mid, which stands for media id.

<div id="thumb" class="ar ar16x9">
  <img mid="850" src="/uploads/850.jpg" />
</div>

Javascript

// instantiate a media picker instance
const picker = new MediaPicker('#thumb');

// get a CSV of the media ids in '#thumb' div
// by default is a string with zero or one id...
// do this in the form submit handler
let mid = picker.csvIDs();

This is another example from the timelines project, showing how the editor for a timeline object allows the user to attach an arbitrary number of images.

Media Picker Multiple Images

The user clicks on Attachments to to launch the Media Picker in order to add media to the attachments, which are rendered as a gallery on the finished page at alasnome.com.

Markup

The markup is straightforward, we just need an element to click and a div to hold the images:

<!-- click this to open MediaPicker dialog -->
<a id="btn-media-pick" href="#">
  <i class="icon-file-plus position-left"></i>
  Attachments
</a>

<div id="gallery" class="row same-height-row">
  <!-- MediaPicker appends selected/uploaded media here -->
</div>

Javascript

As in the prior example, we specify where the images go in the first argument ('#gallery') to the MediaPicker constructor.

But, now we also need to add a couple of simple options:

// instantiate a media picker instance
const picker = new MediaPicker('#gallery', {
    btn: '#btn-media-pick',
    mode: 'append',
    });

// get CSV of media ids in '#gallery' div.
// In append mode this returns 0 or more ids...
// do this in the form submit handler
let mids = picker.csvIDs();

Again, we use the csvIDs() method to get a list of media ids stored in the database. Do this in the submit handler for the editor.


Table Column Example

This example illustrates two options to the MediaPicker that facilitate countless custom applications.

At ThaiDrills we are constantly building data sets that link thai and english, with illustrative media (images, video, audio).

In the table shown we click in the img column to select or upload images to the server.

Let's look at the code and then it will be obvious how the techniques can be generalized to handle any collection of nodes on a page.


Markup

<table id="my-table" class="ar ar16x9">
 <tbody>
  . . .
  <tr> . . . <td class="my-class" /></td><tr>
  <tr> . . . <td class="my-class" /></td><tr>
  . . .
 </tbody>
</table>

Javascript

new MediaPicker('#my-table', {
    selector: 'td.my-class',
    onChange: ($img,$this) => {
        const mid = $img.attr('mid');
        const $tr = $this.closest('tr');
        const row = $tr.index();

        // do something with the image data
        // In our use case, we ajax the eng-thai-img
        // connection straight to the server
        },
    });

When the selector: 'td.my-class' option is used, says to launch the dialog when any node matching this selector is clicked — provided it is contained by the node specified by the first argument to the constructor (i.e. '#my-table').

In other words, this is equivalent to the jQuery, $('#my-table').on('click', 'td.my-class', ...).

The onChange hook allows you to specify a function that is called whenever the image is changed. The routine is passed two jQuery objects: one for the new image, and one for it's immediate parent.

Custom

Sometimes, none of the above techniques will work. This is generally the case when you need to insert media into dynamic elements that didn't exist when the MediaPicker was instantiated.

For instance, ThaiTrills produces Touch Books where each page of a book has a different background image. However, there is one button in the toolbar to set the background image for the current page.

This is a case that is suited to the custom mode which makes this problem easy to handle.

Here are the main considerations: * use the button as the MediaPicker element (i.e. the first argument to constructor) * specify mode: 'custom' as an option * use the onChange option to do whatever you want with the selected image

my.pageBgImgPicker = new MediaPicker('#img-pick-btn', {
    mode: 'custom',
    verbose:!1,
    onChange: ($img) => {
        console.log('background image changed');
        my.$pages.find('.active').append($img);
        },
    });

No Hotlinking

Hotlinking is linking directly to assets, such as images or videos, on a website you don't own.

Don't do this!

It is not only morally wrong, but also problematic to you. Essentially, you are stealing bandwidth from that server (which, the browser may not allow since it is a cross-origin request).

And even if you work around that issue, you are vulnerable to the web site moving or deleting the file in the future and thus breaking your link to it.