Skip to content

Instantly share code, notes, and snippets.

@beckettkev
Created December 17, 2015 12:54
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save beckettkev/e808b5ff5e9f42600ddc to your computer and use it in GitHub Desktop.
Save beckettkev/e808b5ff5e9f42600ddc to your computer and use it in GitHub Desktop.
( function ( workspace, $ ) {
var matches = [];
//this is where we keep track of our refinement items for the Workspace refiner
var workspaceItems;
workspace.Mapping = {
//straight site collection one to one mapping on SPSiteURL. This is detailed in the first part of the scenario.
Simple: {
'Mappings': [
{ 'Label': 'News', 'Relative': '/sites/news' },
{ 'Label': 'Help', 'Relative': '/sites/help' },
{ 'Label': 'Search', 'Relative': '/sites/search' },
{ 'Label': 'Location', 'Relative': '/sites/location' }
],
'RegExpValues' : [
/^\/sites\/news/,
/^\/sites\/help/,
/^\/sites\/search/,
/^\/sites\/location/
]
},
//Used for sounds like matches (e.g. /sites/essentials, /sites/essentials-hr etc..)
Standard: {
'Mappings': [
{ 'Label': 'Essentials', 'Relative': '/sites/essentials' },
{ 'Label': 'Projects', 'Relative': '/sites/project' },
{ 'Label': 'Bids', 'Relative': '/sites/bid' }
],
'RegExpValues': [
/^\/sites\/essentials/,
/^\/sites\/project/,
/^\/sites\/bid/
]
},
//used for multiple differing URL mappings for the communities IA (e.g /sites/communities, /sites/community, /sites/water, /sites/rail-engineering etc..)
Community: {
'Mappings': [
{
'Label': 'Communities', 'Relative': '/sites/communities',
'Label': 'Communities', 'Relative': '/sites/communityengagement',
'Label': 'Communities', 'Relative': '/sites/engineeringpractice',
'Label': 'Communities', 'Relative': '/sites/itdecisions',
'Label': 'Communities', 'Relative': '/sites/communicatingsuccess'
}
],
'RegExpValues' : [
/^\/sites\/communities/,
/^\/sites\/engineeringpractice/,
/^\/sites\/itdecisions/,
/^\/sites\/communicatingsuccess/
]
},
/*
Meanwhile - underneath the community mapping
The Helper Methods (FindCategoryMatch and Category) to check our refinement managed property value against our array mappings (SPSiteURL)
*/
FindCategoryMatch: function (arr, key, url, remember) {
var e = 0;
var valid = arr.some(function (regexp, index, array) {
e = index;
return regexp.test(url);
});
var label = key !== 'Community' ? workspace.Mapping[key].Mappings[e].Label : workspace.Mapping[key].Mappings[0].Label;
var match = { 'Valid': valid, 'Index': e, 'Url': url, 'Name': valid ? label : '' };
//add the new match into the refinement match array if a match is found
if (valid && remember) {
matches.push(match);
}
return match;
},
Category: function (arr, key, url, remember) {
var match, num;
//check to see if we have any matches, if not gather this one and store it in our matches object (in case we need to use the info again)
if (matches.length === 0) {
match = workspace.Mapping.FindCategoryMatch(arr, key, url, remember);
} else {
//check if we have this information already and serve it up if we do (otherwise gather it)
if (matches.some(function (e, index, array) { num = index; return e.Url === url })) {
match = matches[num];
} else {
match = workspace.Mapping.FindCategoryMatch(arr, key, url, remember);
}
}
return match;
}
};
/*
Now we need to include the private internal and public methods for our custom refiner
*/
//This is a cleanup function that removes refinements from a refiner if they are not needed
workspace.RemoveDeadRefinerItems = function (listData) {
var j = workspaceItems.Deletions.length - 1;
//when deleting items from an array, we do it in reverse order to preserve the array indexes integrity.
while (j > -1) {
delete listData[parseInt(workspaceItems.Deletions[j])];
j -= 1;
}
init( );
return listData;
};
//Used for house keeping to reset the internal matches array
workspace.ClearExistingMatches = function ( ) {
//at the start of setting up the refiner, clear down previous matches
matches = [];
};
//internal method used for getting the refinement value for the refinement.
function setRefinementTokens(item, options, url, push) {
if (!push) {
item.RefinementName = options.Name;
}
item.RefinerName = options.Property;
item.Modifier = options.Property;
if (options.Type === 'contains') {
item = addOrPushRefinementToken(item, 'RefinementTokenWrappedValues', '"' + url + '*"', push);
item = addOrPushRefinementToken(item, 'RefinementTokens', '"' + url + '*"', push);
} else if (options.Type === 'equals') {
item = addOrPushRefinementToken(item, 'RefinementTokenWrappedValues', 'equals("' + url + '*")', push);
item = addOrPushRefinementToken(item, 'RefinementTokens', '"ǂǂ' + MyCompany.MyProject.Utilities.stringToHex(url) + '"', push);
}
return item;
}
//internal method for actually setting the refinement values
function addOrPushRefinementToken(item, key, value, push) {
if (push) {
item[key].push(value);
} else {
item[key][0] = value;
}
return item;
}
//house keeping internal method for clearing out unnecessary properties from the refinement JavaScript object if there are now multiple refinement values
function deleteSingleTokenProperties(item, options) {
if (typeof item.RefinementToken !== 'undefined') {
delete item.RefinementToken;
delete item.RefinementValue;
}
return item;
}
//internal method for aggregating the count of a soon to be removed refinement item into the kept refinement and then marking the refinement item for deletion
function removeRefinerItem(item, options) {
workspaceItems[options.Name].Count += item.RefinementCount;
workspaceItems[options.Name].Refinements.push(item.RefinementName);
workspaceItems.Deletions.push(options.Id);
return workspaceItems;
}
//The main method called from the display template to process the refinement item
workspace.SetWorkspaceRefinementItem = function (listData, options) {
var current = null;
//relative url of the refinement item for comparisons
var url = listData[options.Id].RefinementValue.toLowerCase().replace(window.location.protocol + '//' + window.location.host, '');
var base = window.location.protocol + '//' + window.location.host;
//check to see if the refinement item maps to the simple mappings (scenario one)
if (workspace.Mapping.Category(workspace.Mapping.Simple.RegExpValues, 'Simple', url, false).Valid) {
current = workspace.Mapping.Category(workspace.Mapping.Simple.RegExpValues, 'Simple', url, true);
options.Name = typeof options.Name === 'undefined' ? current.Name : options.Name;
listData[options.Id] = setRefinementTokens(listData[options.Id], options, (base + url), false);
listData[options.Id] = deleteSingleTokenProperties(listData[options.Id], options);
//check to see if the refinement item maps to the second scenario
//there maybe more than one mapping to this refinement, but they all should be returned by the same contains statement
} else if (workspace.Mapping.Category(workspace.Mapping.Standard.RegExpValues, 'Standard', url, false).Valid) {
current = workspace.Mapping.Category(workspace.Mapping.Standard.RegExpValues, 'Standard', url, true);
options.Name = typeof options.Name === 'undefined' ? current.Name : options.Name;
//get the refinement item url from the mapping (in case the top result in this mapping differs)
url = workspace.Mapping.Standard.Mappings[current.Index].Relative.indexOf('https:') > -1 ? workspace.Mapping.Standard.Mappings[current.Index].Relative : base + workspace.Mapping.Standard.Mappings[current.Index].Relative;
if (typeof workspaceItems[options.Name] === 'undefined') {
listData[options.Id] = setRefinementTokens(listData[options.Id], options, url, false);
workspaceItems[options.Name] = { 'Id': options.Id, 'Count': listData[options.Id].RefinementCount, 'Refinements': [listData[options.Id].RefinementValue] };
listData[options.Id] = deleteSingleTokenProperties(listData[options.Id], options);
} else {
//we don't want to output this refinement item
workspaceItems = removeRefinerItem(listData[options.Id], options);
//aggregate the refinement item count to include this one and clearup unused properties (if necessary)
listData[workspaceItems[options.Name].Id].RefinementCount = workspaceItems[options.Name].Count;
}
//finally check to see if the refinement item maps to the third and more complex refinement scenario
} else if (workspace.Mapping.Category(workspace.Mapping.Community.RegExpValues, 'Community', url, false).Valid) {
//work out if the community does not start with refiner item sounds like (/sites/communit*) pattern (e.g. /sites/water or /sites/construction-community
var alternate = !workspace.Mapping.Category([workspace.Mapping.Community.RegExpValues[0]], 'Community', url, false).Valid;
//Override the incomming ManagedProperty
options.Property = 'SPSiteURL';
options.Type = 'equals';
current = workspace.Mapping.Category(workspace.Mapping.Community.RegExpValues, 'Community', url, true);
options.Name = typeof options.Name === 'undefined' ? current.Name : options.Name;
//get the refinement item url from the mapping (in case the top result in this mapping differs). We only want to map to /sites/communit
var ending = workspace.Mapping.Community.Mappings[0].Relative;
/*
if it was possible to do two contains int he same query, we could amend the url of the refinement item does not meet the communities pattern, save it in the url variable
url = alternate ? listData[options.Id].RefinementValue : base + ending;
*/
url = listData[options.Id].RefinementValue;
if (typeof workspaceItems[options.Name] === 'undefined') {
//we want our refinement item to point to a specific contains URL which we get from the mappings (ending)
listData[options.Id] = setRefinementTokens(listData[options.Id], options, url, false);
workspaceItems[options.Name] = { 'Id': options.Id, 'Count': listData[options.Id].RefinementCount, 'Refinements': [url] };
listData[options.Id] = deleteSingleTokenProperties(listData[options.Id], options);
} else {
//if (alternate || workspaceItems[options.Name].Refinements.indexOf(url) === -1) {
//this is either a new site (alteranteUrl) or it is the catch all site which we haven't got in the refinement item yet.
//we need to push this url into the Community refinement item (listData[workspaceItems[options.Name].Id]) either way
listData[workspaceItems[options.Name].Id] = setRefinementTokens(listData[workspaceItems[options.Name].Id], options, url, true);
//}
//then update the visible refinment item count to reflect this new total
listData[workspaceItems[options.Name].Id].RefinementCount = workspaceItems[options.Name].Count;
//mark the actual refiner item for deletion
workspaceItems = removeRefinerItem(listData[options.Id], options);
}
//if the refinement item does not map to one of our maps, mark it for deletion.
} else {
//mark the actual refiner item for deletion, it doesn't match one of our products
workspaceItems.Deletions.push(options.Id);
}
//our work here is done.
return listData;
};
//set things up for creating the refiner, this is initialised only when the script is loaded.
function init( ) {
workspaceItems = { 'Deletions': [] };
}
init( );
})( myCompany.myProject.Search.Workspace = myCompany.myProject.Search.Workspace || {}, jQuery );
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment