Differences Between URL and Publishing Image when Developing SharePoint Apps with JavaScript

We’re building a basic slider App Part in SharePoint using all client side code.  We created an App Part for SharePoint and constructed our slider using some publically available JavaScript libraries.

image

The App Part pulls the data from a list mapped by site columns in the App Part’s properties.  Our list has a title, description, and background property to populate the slider’s content. 

There are a couple different methods for storing the image:

  • Custom site column with a URL type
  • Add an existing column such as Page Image or Rollup Image which are of type Publishing Image (these are added to SharePoint when you turn on the publishing features)

There are some significant differences between the two for the end-user supplying the image:

image

The Page Image user interface is definitely better – instead of forcing the end-user to supply the URL to the image, it has a link to the default Site Collection Images library and the user can pick the image from the gallery.  The Page Image also supports Image Renditions which automatically convert images to standard sizes.

image

If you’re writing code that dynamically supports both types of site columns, you’ll run into challenges because parsing out a URL is different than parsing a Publishing image.

The first step is figuring out which site column type you’re dealing with when you fetch the data.  You can query the properties of the list itself and get the field type of the column. 

function schema(listName) {
     this.listName = listName;
     this.fields = [];
     this.addField = function (field) {
         this.fields.push(field);
     };
     this.getField = function (fieldName) {
         var matchingField = null;

        for (i = 0; i < this.fields.length; i++) {
             if (this.fields[i].name == fieldName) {
                 matchingField = this.fields[i];
             }
         }
         return matchingField;
     };
     this.loadSchema = function () {
         hostWebUrl = decodeURIComponent(manageQueryStringParameter(‘SPHostUrl’));
         appWebUrl = decodeURIComponent(manageQueryStringParameter(‘SPAppWebUrl’));

        // create an object to wait on until the Async method below returns
         var deferred = $.Deferred();
         var ctx = new SP.ClientContext(appWebUrl);
         var appCtxSite = new SP.AppContextSite(ctx, hostWebUrl);

        var web = appCtxSite.get_web(); //Get the Web
         var list = web.get_lists().getByTitle(listName); //Get the List
         var fields = list.get_fields();
         ctx.load(fields);
         //Execute the Query Asynchronously
         ctx.executeQueryAsync(
             Function.createDelegate(this, function () {

                var enumerator = fields.getEnumerator();

                while (enumerator.moveNext()) {
                     var listfield = enumerator.get_current();
                     var fieldType = listfield.get_fieldTypeKind();
                     var fieldName = listfield.get_internalName();
                     var field = new schemaField(fieldName, fieldType);
                     this.addField(field);
                 }
                 deferred.resolve(“Success”);
             }),
         Function.createDelegate(this, function () {
             addErrorMessage(“Operation failed  ” + arguments[1].get_message(), 1);
             deferred.reject(“Operation failed”);
        }));
         return deferred.promise();

    };
}

This piece of code takes a list and creates a schema that is stored in memory that describes each of the columns.  This function provides a schema that will allow you to look up the site column in memory and figure out the type. 

SharePoint provides an enumeration called SP.FieldType that you can compare your site column with to figure out its type.  URL, for example, has a field type of 11 and matches to SP.FieldType.URL.

When you query the field type of a Publishing Image, the field type is 0 – this means it’s an “invalid” field type.  Publishing Image isn’t recognized as part of the core standard because its part of the publishing feature infrastructure. 

When you try to pull the value of the field in JavaScript (you’ll see similar behavior in the C# or REST APIs), there are some significant differences:

  • When you retrieve a URL in JavaScript, it comes as a specialized URL object that has a get_url() method for fetching the URL.  This behavior is unique to URL fields.
    url = currentListItem.get_item(imageField).get_url();
  • When you retrieve a Page Image in JavaScript, the field is treated like a normal field in that you can fetch the value with the call:
    url = currentListItem.get_item(imageField);
    However, the format of the content isn’t the URL but the entire image tag, e.g. <img src=…

If you try to call get_item on a URL field, you’ll get an error.  If you’re writing code that needs to fetch the URL out of a Publishing Image field, you’ll have to parse out the image tag to just grab the src attribute.