Task
Short - Access item attribute from a picture library by picture url.
Long - When editing a pagelayout and an image is added to the page, the image's description should be loaded. This is triggered by a button "Get Description" to prevent the user from writing multiple times.
Approach
function GetImageDescription (imageUrl) {
//possible image URLs so far -- additions are welcome !
imageUrl = "http://www.exampleURL/lorem-ipsum.jpg" //does not need to work
imageUrl = "http://root/Sub/PublishingImages/MyFolder/MyFolderN/lorem-ipsum.jpg" //does not work
imageUrl = "http://root/OtherSub/PublishingImages/lorem-ipsum.jpg"; // would work when using correct context.
imageUrl = "http://root/Sub/PublishingImages/lorem-ipsum.jpg"; // works
var libraryUrl = imageUrl.substr(0, imageUrl.lastIndexOf("/")); //trim the picture URL (what about folders ?)
var clientContext = SP.ClientContext.get_current();
var lists = clientContext.get_web().get_lists(); //get all lists
clientContext.load(lists, 'Include(DefaultViewUrl, Title)'); //load lists with needed attributes
clientContext.executeQueryAsync(function (sender, args) {
var enumerator = lists.getEnumerator();
while (enumerator.moveNext()) { //walk over all lists
var list = enumerator.get_current(); //get current list
var listUrl = list.get_defaultViewUrl(); //get somewhat containing the url - View for example
listUrl = listUrl.substr(0, listUrl.lastIndexOf("/Forms")) // trim to get pure list URL
if (endsWith(listUrl, libraryUrl)) { // check if its a match
//list found !
//do awesome stuff
}
}
}, function (sender, args) {
throw "Sadly there occured an error - " + args.get_message() + ' ' + args.get_stackTrace();
});
function endsWith(str, suffix) {
return str.indexOf(suffix, str.length - suffix.length) !== -1;
}
This works as long as there is no folder created.
Update
I took the approach Vadim Gremyachev delivered and added cross site compatibility.
//get absoulute image url
var imageUrl = $("#Image img")[0].src.split("?")[0]; //remove querystring
//get image file properties
getFileProperties(imageUrl, imageUrl);
function getFileProperties(url, fileUrl) {
//to get the file specific client context
//you can create the context based on a url
//the url sadly must match the pure site's url
//exmpl.
//http://contoso/library/image.jpg does not work
//http://contoso/library does not work
//http://contoso does work
//to get the pure site's url I simply add a try
//error query and repeat recursively until no error
//is thrown or the url does not contain "/"
var ctx = new SP.ClientContext(url); //get context
var siteCollection = ctx.get_site(); //try get site to check if context is valid
ctx.load(siteCollection);
ctx.executeQueryAsync(
function () {
// context is valid - proceed
var relUrl = fileUrl.replace(_spPageContextInfo.siteAbsoluteUrl, ''); //convert to relative url
var file = ctx.get_web().getFileByServerRelativeUrl(relUrl); //get file
ctx.load(file, 'ListItemAllFields');
ctx.executeQueryAsync(
function () {
var listItem = file.get_listItemAllFields();
var comment = listItem.get_fieldValues()._Comments;
var copyright = listItem.get_fieldValues().wic_System_Copyright;
$("#Description input").val(comment); //apply
$("#Copyright input").val(copyright);
},
function (sender, args) {
console.log(args.get_message()); //errorhandling
}
);
},
function (sender, args) {
//context is invalid - shrink url and try again
if (url.indexOf("/") !== -1) {
url = url.substr(0, url.lastIndexOf("/"));
getFileProperties(url, fileUrl); //recursive call
}
//else - the url is not compatible
}
);
}