Welcome to the navigation

Ut ut exercitation fugiat in cupidatat dolor voluptate adipisicing in veniam, aute nulla laboris excepteur dolore tempor sed incididunt commodo ullamco ex et nisi ut. Consequat, excepteur sit exercitation labore ut dolore ut culpa anim adipisicing aute ipsum reprehenderit dolor consectetur enim minim sed nulla aliquip veniam, quis nostrud elit

Yeah, this will be replaced... But please enjoy the search!

Insert alt tag from ImageVault into TinyMCE

Since inserting images from the ImageVault Gadget isn't supported by drag and drop in Episerver we must rely on the ImageVault TinyMCE plugin which we can interact with using the imagevault-tinymce.js library. I've already covered parts of this topic in the following post Modifying the default image tag inserted by ImageVault in Episerver TinyMCE.

Fetching MetaData

The issue in this implementation is that the serialized ImageVault.Common.Data.Media class doesn't contain any metadata when added to the editor.

Luckily there is an API we can call to fetch the metadata from, the fairly undocumented and probably considered internal API ImageVaultBrowserStore which resides in the ImageVault.EPiServer.UI.Stores namespace.

This API is typically used to list the images in the Episerver Gadget but it does also include the Metadata in the result. The get method in the API got the following parameters

Get(string query, int[] categories, IvItemRange range)

// IvItemRange 
public int? Start { get; set; }
public int? End { get; set; }
public int? Total { get; set; }

Example usage

// Get the default listing
/EPiServer/ImageVault.EPiServer.UI/Stores/imagevaultbrowserstore/

// Get the image with ID 2949, end=0 will ensure only the first item is fetched
/EPiServer/ImageVault.EPiServer.UI/Stores/imagevaultbrowserstore/?query=2949&end=0

// Get images with category 54 set
/EPiServer/ImageVault.EPiServer.UI/Stores/imagevaultbrowserstore/?categories=54

// Get images with category 56 AND 56 set 
/EPiServer/ImageVault.EPiServer.UI/Stores/imagevaultbrowserstore/?categories=54&categories=56

// Category ID's can be fetched from the ImageVaultCategoryStore API
/EPiServer/ImageVault.EPiServer.UI/Stores/imagevaultcategorystore

The result from the browserstore will include the MetaData from ImageVault.

With that sorted simply implement it in the addMediaToEditor implementation of imagevault-tinymce.js. For illustrative purposes, I've done everything as simple as possible.

/*
 * Inserts media (if any) into the editor
 * source: www.herlitz.io
 */
function addMediaToEditor(media) {
   
    // Change this property name accordingly to the meta field you want to write to the image alt-tag from ImageVault
    var altIVPropertyName = "Alt";

    if (media) {
        // Default implementation
        //editor.insertContent(media.MediaConversions[0].Html);

        // todo: Add this if we want to handle video in editor instead of images if not Original
        //    if(media.ContentType.indexOf("video") !== -1)
        //        editor.insertContent(media.MediaConversions[2].Html);
        //    else
        //        editor.insertContent(media.MediaConversions[0].Html);


        // Custom implementation below
        // Keep it simple, still need IE compatibility... :_(
        try {
            // Fetch the first conversion
            var mediaConversion = media.MediaConversions[0],
                altText = "";

            getIVMediaObjects(media.Id, function (response) {
                if (response.status === 200 && response.responseText) {
                    // Array of mediaobjects
                    var mediaObjects = JSON.parse(response.responseText);

                    if (mediaObjects && mediaObjects.length > 0) {
                        // fetch first from array
                        var mediaObject = mediaObjects[0];

                        if (mediaObject.Metadata && mediaObject.Metadata.length > 0) {
                            // Get the alt data from medadata container

                            var altData = mediaObject.Metadata.filter(function (meta) {
                                return meta.Name === altIVPropertyName;
                            });

                            if (altData && altData.length > 0) {
                                // we got some alt-text
                                altText = altData[0].StringValue;
                                console.log(altData[0]);
                            }
                        }
                    }

                    // Reply from the api, preferr the altText but fallback to the media.Name
                    writeImage(mediaConversion, altText ? altText : media.Name);
                } else {
                    // No reply from the api, use the mediaConversion and media.Name to set alt/title
                    writeImage(mediaConversion, media.Name);
                }
            });
        } catch (e) {
            // so we got an error, the mediaConversion will however still be alright
            console.error(e.message);

            // Ensure image is written
            writeImage(mediaConversion, media.Name);
        }
    }
}

/*
 * Write the image to the editor
 */
function writeImage(mediaConversion, altText) {
    // set format css class 
    var format = "image-format-square";
    if (mediaConversion.AspectRatio < 1) format = "image-format-portrait";
    if (mediaConversion.AspectRatio > 1) format = "image-format-landscape";

    // set up image element
    var img = document.createElement("img");
    img.src = mediaConversion.Url;
    img.className = "iv-editor-image ".concat(format);

    // set alt and title
    altText = cleanUpAlt(altText);
    img.alt = altText;
    img.title = altText;

    // add image to editor
    editor.insertContent(img.outerHTML);
}

/*
 * Clean up file endings in altText
 */
function cleanUpAlt(altText) {

    var altTextLower = altText.toLowerCase();

    // look for forbidden file name endings
    if (altTextLower.indexOf(".png") > -1
        || altTextLower.indexOf(".jpg") > -1
        || altTextLower.indexOf(".bmp") > -1
        || altTextLower.indexOf(".svg") > -1
    ) {
        return altText.substring(0, altText.lastIndexOf('.')) || altText;
    }

    return altText;
}


/*
 * Query ImageVault for the media object
 */
function getIVMediaObjects(id, callback) {
    var XHR = null;

    // query the imagevaultbrowserstore, end=0 ensures we only fetch the first element
    var url = "/EPiServer/ImageVault.EPiServer.UI/Stores/imagevaultbrowserstore/?query=" + id + '&end=0';

    if (window.XMLHttpRequest) {
        XHR = new XMLHttpRequest();
    } else {
        XHR = new ActiveXObject("Microsoft.XMLHTTP");
    }

    XHR.onreadystatechange = function () {
        if (XHR.readyState === 4 || XHR.readyState === "complete") {
            if (XHR.status === 200) {
                callback(XHR);
            } else {
                console.error("Query failed");
            }

        }
    };

    XHR.open("GET", url, true);
    XHR.send(null);
}

This should insert the alt and title field into the TinyMCE editor will media name fallback.

<img class="iv-editor-image image-format-landscape" 
   title="Illustration av en fotbollsspelare" 
   alt="Illustration av en fotbollsspelare"
   src="/imagevault/media/dx6dfmfww23qtqshyery/Puff_S-dert-ljecupen.png" />