Sharepoint 2013 search: how to make refiner update 2 search web parts
So my case today is having a nice Search Results Page, with a nice Search Results WP and a Refinement WP updating him.
now i added another Content Search WP, and Oh My! it doesnt updates!
since i am used to MS giving a lot of work to developers, that looked like a nice challenge, some advanced client-side Search-Controls work.
so...
var rgx = /#Default={[{":,\\}()#\-\[\]a-zA-Z0-9]+}/;
var queryObjStr = decodeURIComponent(window.location.hash)
.match(rgx)[0].replace("#Default=", "");
var cc = ctx.ClientControl;
cc.raiseQueryReadyEvent(queryStateArgs)
basically if you need some very specific logic you can end reading here.
also note that the you can create your own QueryState object and fill it as you wish like here, just google it a bit.
but......
I. After one click it doesn't work again
II. Sometimes it doesn't catch the Refiner Control/s
III. The script never Runs if no initial results
now i added another Content Search WP, and Oh My! it doesnt updates!
since i am used to MS giving a lot of work to developers, that looked like a nice challenge, some advanced client-side Search-Controls work.
so...
1 - Get the new query
that part is easy - its up in the url, with a simple regex i took it out
var rgx = /#Default={[{":,\\}()#\-\[\]a-zA-Z0-9]+}/;
var queryObjStr = decodeURIComponent(window.location.hash)
.match(rgx)[0].replace("#Default=", "");
2 - Send it to our control
well, MS did gace us some nice Client-Side API, one of the SRCH objects is the QueryState, which is actually the object in the Default up in our hash
var queryState = JSON.parse(queryObjStr);
var queryStateArgs = new Srch.QueryEventArgs(queryState);
var queryStateArgs = new Srch.QueryEventArgs(queryState);
//and tell our control to update
var cc = ctx.ClientControl;
cc.raiseQueryReadyEvent(queryStateArgs)
also note that the you can create your own QueryState object and fill it as you wish like here, just google it a bit.
but......
3 - Put it in your Control Display Template
but i want my WP to be independent, meaning that wherever i throw it around it will know what to do, i.e. update itself from the page refiners.
so obviously i want to put all this login in my Control Display Template
AddPostRenderCallback(ctx, function(){
$('a[id=FilterLink]').on("click", function(){
console.log('u clicked me!!');
var rgx = /#Default={[{":,\\}()#\-\[\]a-zA-Z0-9]+}/;
var queryObjStr = decodeURIComponent(window.location.hash)
.match(rgx)[0].replace("#Default=", "");
var queryState = JSON.parse(queryObjStr);
var queryStateArgs = new Srch.QueryEventArgs(queryState);
var cc = ctx.ClientControl;
cc.raiseQueryReadyEvent(queryStateArgs);
});
});
$('a[id=FilterLink]').on("click", function(){
console.log('u clicked me!!');
var rgx = /#Default={[{":,\\}()#\-\[\]a-zA-Z0-9]+}/;
var queryObjStr = decodeURIComponent(window.location.hash)
.match(rgx)[0].replace("#Default=", "");
var queryState = JSON.parse(queryObjStr);
var queryStateArgs = new Srch.QueryEventArgs(queryState);
var cc = ctx.ClientControl;
cc.raiseQueryReadyEvent(queryStateArgs);
});
});
so...that should have done it... but....
4 - The "Bugs"
II. Sometimes it doesn't catch the Refiner Control/s
III. The script never Runs if no initial results
well, for bugs I and II i created a nice interval system, shown immediately, but for III its simple, in the WP Properties uncheck "Dont show anything when there are no results"
for the rest, the point is that all this stuff happens ASYNC, and i found no "OnPostEverything" event or callback, so i just used an interval
var overloadRefiners = function () {
console.log('overloading Refiners : ' + $('a[id=FilterLink]').length);
var setRefinerOn = function () {
console.log('setRefinerOn, attempt ' + window.setRefinerOnCount);
if (++window.setRefinerOnCount > 5) {
console.warn('clearing window.setRefinerOnCount after 5 tries');
clearInterval(window.setRefinerOnInterval);
}
if ($("[refinername]").length === 0) {
console.warn('overloading Refiners : no refiner found');
return;
}
$("[refinername]").on("click", "a[id=FilterLink]", function () {
console.log('overload Refiner click')
var rgx = /#Default={[{":,\\}()#\-\[\]a-zA-Z0-9]+}/;
var queryObjStr = decodeURIComponent(window.location.hash)
.match(rgx)[0].replace("#Default=", "");
var queryState = JSON.parse(queryObjStr);
var queryStateArgs = new Srch.QueryEventArgs(queryState);
var cc = ctx.ClientControl;
cc.raiseQueryReadyEvent(queryStateArgs)
});
clearInterval(window.setRefinerOnInterval);
};
window.setRefinerOnCount = 0;
window.setRefinerOnInterval = setInterval(setRefinerOn, 100);
}//end overloadRefiners
AddPostRenderCallback(ctx, overloadRefiners);
for the rest, the point is that all this stuff happens ASYNC, and i found no "OnPostEverything" event or callback, so i just used an interval
var overloadRefiners = function () {
console.log('overloading Refiners : ' + $('a[id=FilterLink]').length);
var setRefinerOn = function () {
console.log('setRefinerOn, attempt ' + window.setRefinerOnCount);
if (++window.setRefinerOnCount > 5) {
console.warn('clearing window.setRefinerOnCount after 5 tries');
clearInterval(window.setRefinerOnInterval);
}
if ($("[refinername]").length === 0) {
console.warn('overloading Refiners : no refiner found');
return;
}
$("[refinername]").on("click", "a[id=FilterLink]", function () {
console.log('overload Refiner click')
var rgx = /#Default={[{":,\\}()#\-\[\]a-zA-Z0-9]+}/;
var queryObjStr = decodeURIComponent(window.location.hash)
.match(rgx)[0].replace("#Default=", "");
var queryState = JSON.parse(queryObjStr);
var queryStateArgs = new Srch.QueryEventArgs(queryState);
var cc = ctx.ClientControl;
cc.raiseQueryReadyEvent(queryStateArgs)
});
clearInterval(window.setRefinerOnInterval);
};
window.setRefinerOnCount = 0;
window.setRefinerOnInterval = setInterval(setRefinerOn, 100);
}//end overloadRefiners
AddPostRenderCallback(ctx, overloadRefiners);
some extra links for start
Comments
Post a Comment