Determine Rules triggered by endeca - endeca

We have various endeca rules set up through Rules Manager in our application which are triggered while rendering the page.
Is it possible to determine which rule was triggered for a page through Java/JSP code?

The proper way to do this is with the Content Assembler API (endeca_content.jar). You need to create a content query and retrive the content object:
ContentItem content = results.getContent();
content.getName();
It is also possible to use the navigation API, using the SupplementList object from the navigation object: The title key will represent the name of the rule triggered. However, is you are using page builder in any meaningful way the proper approach is to use the Content Assemble API.
SupplementList sl = nav.getSupplements();
for (Object object : sl) {
Supplement s = (Supplement) object;
PropertyMap map = s.getProperties();
Set keys = map.keySet();
for (Object key : keys) {
logger.info("Sup prop: " + key + " \t" + map.get(key));
}
}

Related

IG - how to register changes to cell being edited - eg. to action shortcut key (Oracle Apex Interactive Grid)

We have common functionality across multiple pages: Cancel/Save/Back/Next (buttons).
I added shortcut keys via app-level static JavaScript file: Alt-C/S/B/N (using common CSS on the buttons & jQuery binds).
Problem: when using shortcut key whilst editing a cell, the edits to the cell were not saved with Alt-S, Alt-N. (For same reason, no confirmation requested on Cancel/Back, since the grid did not see any changes.)
Much searching and reading of documentation did not reveal the answer...
After a huge amount of effort: inspecting of widget/ interactiveGrid/ model/ getCurrentView via the console & inspect-panes (partly because I didn't find/inspect the .interactiveGrid('getViews','grid).getColumns() for a long time), I found a solution, but I feel there must be a more elegant one. Advice sought! TIA.
Here is my solution. Note the namespace is lps, and I have aliased apex.jQuery as lps.$ prior to the code below. I include comments for my Oracle colleagues less experienced with JS, Apex, jQuery, etc.
The solution works for all 4 shortcut keys, and should work for any IG (possibly even without a static id on the containing region, although my test case has a static id). There is some supporting code after the main solution. All happening on page load via the static JS file.
The jQuery selectors must only bind to a single button on each page!
lps.$(window).on('keydown',function($evt) // Capture Alt + shortcut key in keydown event
{
// $evt is the jQuery simplified event
if( $evt.altKey ) // the alt-key is being pressed-and-held
{
var key = $evt.key.toUpperCase();
if( lps.shortcuts[key] )
{
if( lps.$($evt.target).is('input,textarea') ) // effect the onchange() JavaScript (more specifically, the IG version thereof)
{
// We've pressed a shortcut key combo, whilst editing a cell, so the IG-onchange-y event hasn't yet fired
var tgtEle = $evt.target,
newVal = tgtEle.value, // the value of the on-screen element, regardless of change-status
tgtId = tgtEle.id, // this tallies with an elementId exposed via the igCols below
activeFld;
// IG stuff - igId - get the IG overall id via an IG ancestor div of the target field, then losing the trailing _ig suffix
var igId = lps.$(tgtEle).parents('div.a-IG')[0].id.replace(/_ig$/,'')
igWidget= apex.region(igId).widget(),
igGrid = igWidget.interactiveGrid('getViews','grid'),
igModel = igGrid.model,
igView = igWidget.interactiveGrid('getCurrentView'),
igRecId = igView.getActiveRecordId(),
igCols = igGrid.getColumns(); // this provides meta information about the columns in the IG
for( var i=-1; ++i<igCols.length; ) // find the field name of this IG-column from target element id
{
if( igCols[i].elementId === tgtId )
{
activeFld = igCols[i].property;
break;
}
}
// Phew. Eventually setValue on the IG-cell so Apex knows the cell has changed without an onchange firing
igModel.setValue(igModel.getRecord(igRecId),activeFld,newVal);
}
$evt.originalEvent.preventDefault(); // we're consuming the event, so stop it doing some native browser trick we don't want
lps.$(lps.shortcuts[key].selector).select(); // select the to-be-clicked-element
lps.$(lps.shortcuts[key].selector).click(); // synthesise a click on the selector'd element
}
}
});
Supporting code to pre-establish what our 4 shortcut keys are to be:
lps.shortcuts = { // keys and their jQuery selectors
B : { selector:'button.nav-back' },
C : { selector:'button.nav-cancel' },
N : { selector:'button.nav-next' },
S : { selector:'button.nav-save' },
};
Code to add hover-title to the buttons:
// Advertise the shortcut with a 'title' attribute (appears as popup tip when hover over the element)
for( var key in lps.shortcuts ){
lps.$(lps.shortcuts[key].selector).attr('title','Alt+'+key);
}

Get current page request url in handlebars?

Is there a way to the current request url or path in Handlebars? I need to be able to switch what parts of the theme is loaded based on paths. I've tried {{url}} ... no luck. Using latest Stencil with Cornerstone.
I had to do something like this for a project with 3 different category page layouts. Without custom category templates in Stencil, you have to get a little creative.
First, inject the handlebars URL into your category.js file using the BigCommerce's inject handlebar helper seen here. Then parse it so you get only the unique parts, then perform some logic based on what you want to do.
I used the breadcrumb li length as an indicator of how deep I was in the category tree. There is likely a better way, but this is what I thought of first, and it worked just fine.
category.html
{{inject "currentPage" category.url}}
category.js
var pageURL = this.context.currentPage;
var pageURL = pageURL.replace(/\//g," ").replace("http:","").replace("storeurl.mybigcommerce.com","").replace("storeurl.com","").trim();
var catName = pageURL.substr(0,pageURL.indexOf(' '));
console.log('pageURL = ' + pageURL);
console.log('catName = ' + catName);
console.log($('ul.breadcrumbs li').length);
if( $('ul.breadcrumbs li').length == 3 ){
if(catName == "black-decker"){
if($(".cat-img").length){
$(".page").addClass("model-list");
$(".cat-img").hide();
$(".page").append("<div class='model-wrap'><div class='model-catalog' data-reveal-id='myModal'><span class='click-larger'>Click to view larger</span></div></div>");
$(".sidebarBlock-heading").text("Select Your Model Number Below:");
$(".brand-img").each(function(){
$(this).addClass(catName);
});
} else {
$(".page").addClass("model-list");
$(".sidebarBlock-heading").text("Select Your Model Number Below:");
$(".brand-img").each(function(){
$(this).addClass(catName);
});
// make page full width
$(".page-sidebar.cf.Left").addClass("full-width");
}
}
// MORE CODE etc...

How to accept user input in thesaurus api to display synonyms using flash as3

am working on a project to develop a thesaurus app using flash as3. However my app works fine but it only displays the synonym for the word already being put inside the thesaurus API url. However, I want my app to allow any user input through the input text field. Is there a way to do that? Many thanks in advance. I use "Big Huge Thesaurus API" for synonyms. For example in below API URL only synonyms for word "mother" are displayed.
"http://words.bighugelabs.com/api/2/958af28ac9e3b21c650cbdd24a2466e8/mother/"
Here is my full code.
button1.addEventListener(MouseEvent.CLICK, loadScores);
function loadScores(e:MouseEvent):void {
var fileLoader:URLLoader = new URLLoader();
fileLoader.addEventListener(Event.COMPLETE, scoresLoadComplete);
fileLoader.load(new URLRequest("http://words.bighugelabs.com/api/2/958af28ac9e3b21c650cbdd24a2466e8/mother/"));
}
function scoresLoadComplete(evt:Event):void {
try {
var returnVars = evt.target.data;
highscores.htmlText = returnVars;
trace("Data retrieved successfully");
for (var myVars in returnVars) {
trace(myVars + ": " + returnVars[myVars]);
}
trace("***********************");
} catch (err:Error) {
trace("Can't parse loaded file: " + err.message);
}
}
Have an input text box in your application and set its instance name to "userinput" and change the following line in your code.
fileLoader.load(new URLRequest("http://words.bighugelabs.com/api/2/958af28ac9e3b21c650cbdd24a2466e8/mother/"));
to
fileLoader.load(new URLRequest("http://words.bighugelabs.com/api/2/958af28ac9e3b21c650cbdd24a2466e8/"+userinput.text+"/"));

Should Durandal url hashes include the id?

Using the HTML Starter Kit example for Durandal 2.0.1.
If I add a route for customers/:id with my own vm and view I can navigate to the page c://temp/index.html#customer/123 and the page displays and in activate I can see the parameter of 123. However, the hash for that page shows as customer/:id Should the router automatically update these hashes to include any passed parameters or is this something I have to do myself?
There may be a baked in fix for this but if you are going to be using the hash and you have the Id or optional Id stuff in there you can use this helper for navigation and to clean up the hash, if needed -
function changeRoute(route) {
var cleanRoute = route.hash;
if (cleanRoute.indexOf(':id') !== -1) {
cleanRoute = cleanRoute.replace(':id', '');
}
return router.navigate('#' + thisRoute);
}
Or you could just as easily add an additional setting on the route to use as the cleaned hash.

MVC SiteMap - when different nodes point to same action SiteMap.CurrentNode does not map to the correct route

Setup:
I am using ASP.NET MVC 4, with mvcSiteMapProvider to manage my menus.
I have a custom menu builder that evaluates whether a node is on the current branch (ie, if the SiteMap.CurrentNode is either the CurrentNode or the CurrentNode is nested under it). The code is included below, but essentially checks the url of each node and compares it with the url of the currentnode, up through the currentnodes "family tree".
The CurrentBranch is used by my custom menu builder to add a class that highlights menu items on the CurrentBranch.
The Problem:
My custom menu works fine, but I have found that the mvcSiteMapProvider does not seem to evaluate the url of the CurrentNode in a consistent manner:
When two nodes point to the same action and are distinguished only by a parameter of the action, SiteMap.CurrentNode does not seem to use the correct route (it ignores the distinguishing parameter and defaults to the first route that that maps to the action defined in the node).
Example of the Problem:
In an app I have Members.
A Member has a MemberStatus field that can be "Unprocessed", "Active" or "Inactive". To change the MemberStatus, I have a ProcessMemberController in an Area called Admin. The processing is done using the Process action on the ProcessMemberController.
My mvcSiteMap has two nodes that BOTH map to the Process action. The only difference between them is the alternate parameter (such are my client's domain semantics), that in one case has a value of "Processed" and in the other "Unprocessed":
Nodes:
<mvcSiteMapNode title="Process" area="Admin" controller="ProcessMembers" action="Process" alternate="Unprocessed" />
<mvcSiteMapNode title="Change Status" area="Admin" controller="ProcessMembers" action="Process" alternate="Processed" />
Routes:
The corresponding routes to these two nodes are (again, the only thing that distinguishes them is the value of the alternate parameter):
context.MapRoute(
"Process_New_Members",
"Admin/Unprocessed/Process/{MemberId}",
new { controller = "ProcessMembers",
action = "Process",
alternate="Unprocessed",
MemberId = UrlParameter.Optional }
);
context.MapRoute(
"Change_Status_Old_Members",
"Admin/Members/Status/Change/{MemberId}",
new { controller = "ProcessMembers",
action = "Process",
alternate="Processed",
MemberId = UrlParameter.Optional }
);
What works:
The Html.ActionLink helper uses the routes and produces the urls I expect:
#Html.ActionLink("Process", MVC.Admin.ProcessMembers.Process(item.MemberId, "Unprocessed")
// Output (alternate="Unprocessed" and item.MemberId = 12): Admin/Unprocessed/Process/12
#Html.ActionLink("Status", MVC.Admin.ProcessMembers.Process(item.MemberId, "Processed")
// Output (alternate="Processed" and item.MemberId = 23): Admin/Members/Status/Change/23
In both cases the output is correct and as I expect.
What doesn't work:
Let's say my request involves the second option, ie, /Admin/Members/Status/Change/47, corresponding to alternate = "Processed" and a MemberId of 47.
Debugging my static CurrentBranch property (see below), I find that SiteMap.CurrentNode shows:
PreviousSibling: null
Provider: {MvcSiteMapProvider.DefaultSiteMapProvider}
ReadOnly: false
ResourceKey: ""
Roles: Count = 0
RootNode: {Home}
Title: "Process"
Url: "/Admin/Unprocessed/Process/47"
Ie, for a request url of /Admin/Members/Status/Change/47, SiteMap.CurrentNode.Url evaluates to /Admin/Unprocessed/Process/47. Ie, it is ignorning the alternate parameter and using the wrong route.
CurrentBranch Static Property:
/// <summary>
/// ReadOnly. Gets the Branch of the Site Map that holds the SiteMap.CurrentNode
/// </summary>
public static List<SiteMapNode> CurrentBranch
{
get
{
List<SiteMapNode> currentBranch = null;
if (currentBranch == null)
{
SiteMapNode cn = SiteMap.CurrentNode;
SiteMapNode n = cn;
List<SiteMapNode> ln = new List<SiteMapNode>();
if (cn != null)
{
while (n != null && n.Url != SiteMap.RootNode.Url)
{
// I don't need to check for n.ParentNode == null
// because cn != null && n != SiteMap.RootNode
ln.Add(n);
n = n.ParentNode;
}
// the while loop excludes the root node, so add it here
// I could add n, that should now be equal to SiteMap.RootNode, but this is clearer
ln.Add(SiteMap.RootNode);
// The nodes were added in reverse order, from the CurrentNode up, so reverse them.
ln.Reverse();
}
currentBranch = ln;
}
return currentBranch;
}
}
The Question:
What am I doing wrong?
The routes are interpreted by Html.ActionLlink as I expect, but are not evaluated by SiteMap.CurrentNode as I expect. In other words, in evaluating my routes, SiteMap.CurrentNode ignores the distinguishing alternate parameter.
I think it is because you are trying to obtain the route FROM the parameters. Basically, MVC is just trying to GUESS what route you could be referring to.
The correct way would be to handle routes by name. So the sitemap should reference to a Route name rather than the Controller, action, etc.
Addendum - I've got it to work!!:
The big stumbling block:
When using different routes to point at the same controller action, so that one has different nodes, the big problem I had was the following:
YOU MUST GIVE THE DIFFERENT NODES A KEY!!! OTHERWISE THE SITEMAP WON'T RENDER!!
EG, just the route attribute on its own is NOT enough and you MUST give each node that point to the same action a UNIQUE key to distinguish them from each other:
<mvcSiteMapNode title="Edit Staff" area="Admin" controller="EditStaff" route="Admin_AdministratorDetails" action="Start" key="administrators_details" />
<mvcSiteMapNode title="Edit Staff" area="Admin" controller="EditStaff" route="Admin_StaffDetails" action="Start" key="staff_details" />
Once I realised that, it is now plain sailing. Otherwise, all is obscure and obtuse.
NOTE:
In the question, the action that was getting called by different routes was the Process action. I changed that to calls to different actions. But when editing my objects (Solicitors), I couldn't do that, as the editing is done by an MVC Wizard that, like my custom menu builder, I have written and works very well. It just simply wasn't possible (or rather, DRY) to recreate the wizard three times. So I HAD to get my menu higlighting working correctly with different routes pointing at the same action.
No Un-DRY fudges will do. My client doesn't deserve it.
The Solution (see NOTE as to why the actions and routes are different to the question):
The suggestion by Carlos Martinez works, but you need to use Html.RouteLink as opposed to Html.ActionLink, in conjunction with the edited sitemap, that details the routes.
Essentially, in your nodes, you need to use the route attribute:
<mvcSiteMapNode title="Details Active Solicitor" area="Solicitors" controller="EditSolicitor" action="Start" route="Active_Details" key="company_activeSolicitors_details"/>
Then, in your views, instead of action links, you use the RouteLink helper:
#Html.RouteLink("Details", "Active_Details", new { action="Start", controller="EditSolicitor", idSolicitor = item.SolicitorId, returnUrl = Request.RawUrl })
In your route registration file, you can now write routes that call the same action:
context.MapRoute(
"Unprocessed_Details",
"Unprocessed/Edit/{idSolicitor}/{action}",
new { action = "Start", controller = "EditSolicitor", idSolicitor = UrlParameter.Optional }
);
context.MapRoute(
"Inactive_Details",
"Inactive/Edit/{idSolicitor}/{action}",
new { controller = "EditSolicitor", action = "Start", idSolicitor = UrlParameter.Optional }
);
context.MapRoute(
"Active_Details",
"Solicitors/Edit/{idSolicitor}/{action}",
new { controller = "EditSolicitor", action = "Start", idSolicitor = UrlParameter.Optional }
);
As you can see, it is the exact same action that is getting called by the three routes. So long as I specify the route name in the mvcSiteMapNode, the routes are correctly distinguished when my menu is built and the highlighting works as required.
Note on getting befuddled with XML:
I hate XML, deeply and truly. It boggles and befuddles me, especially when I have a cold.
The problem being that adding the route attribute to the mvcSiteMapNodes adds to the potential for befuddlement.
And befuddled I got
I had initially tried Carlos' suggestion, but it didn't work. Not sure what the error was, but went through it with a tooth comb and it is now working. The annoying thing is that I am not sure what I was doing wrong.
Living in Hope:
I hope this documents an albeit fringe aspect of mvcSiteMapNode.
Just in case, can you try the following:
context.MapRoute(
"Process_New_Members",
"Admin/{alternate}/Process/{MemberId}",
new { controller = "ProcessMembers",
action = "Process",
alternate="Unprocessed",
MemberId = UrlParameter.Optional }
);
This way you will be distinguishing between each route by requiring this additional parameter.
You can use url in your mvcSiteMapNode. like below:
<mvcSiteMapNode title="Process" area="Admin" controller="ProcessMembers" action="Process" aurl="/Admin/ProcessMembers/Process/Unprocessed"/>
<mvcSiteMapNode title="Change Status" area="Admin" controller="ProcessMembers" action="Process" url="/Admin/ProcessMembers/Process/Processed" />
Of course, you should use the appropriate RoutConfig for the url to work.
there is a sample here.