KRL Search annotation rules for multiple domains, divs inserting for each domain whether domain matches or not - krl

My KRL search annotation ruleset contains 4-5 rules that each do annotation based on the domain in the search results. I am getting good results, in that the annotations are pretty much when and where they should. However, as I look at the source code in the browser, each rule is inserting a div into the html whether any annotation should occur for that domain or not. There is nothing on visible the page to suggest it, but I don't want to add any unnecessary code and keep this light.
Is there a way to instruct those rules that do not annotate for a result to not place any code into the page? (btw - right now I'm using all local data - I will be doing a remote call later on after this is tested and realize that will solve this issue).
Two of my rules:
rule search_annotate_party is active {
select using "google.com|bing.com/search|search.yahoo.com/search" setting()
every {
emit <<
function annotate_party(toAnnotate, wrapper, data) {
if (data.domain == "www.mydomain.com" ) {
wrapper.append("<div style='border: 1px dashed orange'><a href='http://www.mydomain.com/search.do?query=some+product' target='_blank'><img src=https://dl.dropbox.com/u/3287029/product_image.png width='100%'></a></div>");
wrapper.show();
}
}
>>;
annotate:annotate("party") with
annotator = <| annotate_party |>;
}
}
rule search_annotate_jiffy is active {
select using "google.com|bing.com/search|search.yahoo.com/search" setting()
every {
emit <<
function annotate_jiffy(toAnnotate, wrapper, data) {
if (data.domain == "www.hisdomain.com" ) {
wrapper.append("<div style='border: 0px solid red'><img src=http://dl.dropbox.com/u/3287029/company_logo.jpg>");
wrapper.show();
}
}
>>;
annotate:annotate("jiffy") with
annotator = <| annotate_jiffy |>;
}
}

Related

xPages REST Service Results into Combobox or Typeahead Text Field

I've read all the documentation I can find and watched all the videos I can find and don't understand how to do this. I have set up an xPages REST Service and it works well. Now I want to place the results of the service into either a combobox or typeahead text field. Ideally I would like to know how to do it for both types of fields.
I have an application which has a view containing a list of countries, another view containing a list of states, and another containing a list of cities. I would like the first field to only display the countries field from the list of data it returns in the XPages REST Service. Then, depending upon which country was selected, I would like the states for that country to be listed in another field for selection, etc.
I can see code for calling the REST Service results from a button, or from a dojo grid, but I cannot find how to call it to populate either of the types of fields identified above.
Where would I call the Service for the field? I had thought it would go in the Data area, but perhaps I've just not found the right syntax to use.
November 6, 2017:
I have been following your suggestion, but am still lost as can be. Here's what I currently have in my code:
x$( "#{id:ApplCountry}" ).select2({
placeholder: "select a country",
minimumInputLength: 2,
allowClear : true,
multiple: false,
ajax: {
dataType: 'text/plain',
url: "./Application.xsp/gridData",
quietMillis: 250,
data: function (params) {
return {
search:'[name=]*'+params.term+'*',
page: params.page
};
},
processResults: function (data, page) {
var data = $.map(data, function (obj) {
obj.id = obj.id || obj["#entityid"];
obj.text = obj.text || obj.name;
return obj;
});
},
return {results: data};
}
}
});
I'm using the dataType of 'text/plain' because that was what I understood I should use when gathering data from a domino application. I have tried changing this to json but it makes no difference.
I'm using processResults because I understand this is what should be used in version 4 of select2.
I don't understand the whole use of the hidden field, so I've stayed away from that.
No matter what I do, although my REST service works if I put it directly in the url, I cannot get any data to display in the field. All I want to display in the field is the country code of the document, which is in the field named "name" (not my choice, it's how it came before I imported the data from MySQL.
I have read documentation and watched videos, but still don't really understand how everything fits together. That was my problem with the REST service. If you use it in Dojo, you just put the name of the service in a field on the Dojo element and it's done, so I don't understand why all the additional coding for another type of domino element. Shouldn't it work the same way?
I should point out that at some points it does display the default message, so it does find the field. Just doesn't display the country selections.
I think the issue may be that you are not returning SelectItems to your select2, and that is what it is expecting. When I do something like you are trying, I actually use a bean to generate the selection choices. You may want to try that or I'm putting in the working part of my bean below.
The Utils.getItemValueAsString is a method I use to return either the string value of a field, or if it is not on the document/empty/null an empty string. I took out an if that doesn't relate to this, so there my be a mismatch, but I hope not.
You might be able to jump directly to populating the arrayList, but as I recall I needed to leverage the LinkedHashMap for something.
You should be able to do the same using SSJS, but since that renders to Java before executing, I find this more efficient.
For label/value pairs:
LinkedHashMap lhmap = new LinkedHashMap();
Document doc = null;
Document tmpDoc = null;
allObjects.addElement(doc);
if (dc.getCount() > 0) {
doc = dc.getFirstDocument();
while (doc != null) {
lhmap.put(Utils.getItemValueAsString(doc, LabelField, true), Utils.getItemValueAsString(doc, ValueField, true));
}
tmpDoc = dc.getNextDocument(doc);
doc.recycle();
doc = tmpDoc;
}
}
List<SelectItem> options = new ArrayList<SelectItem>();
Set set = lhmap.entrySet();
Iterator hsItr = set.iterator();
while (hsItr.hasNext()) {
Map.Entry me = (Map.Entry) hsItr.next();
// System.out.println("after: " + hStr);
SelectItem option = new SelectItem();
option.setLabel(me.getKey() + "");
option.setValue(me.getValue() + "");
options.add(option);
}
System.out.println("About to return from generating");
return options;
}
I ended up using straight up SSJS. Worked like a charm - very simple.

How to overlay a cq widget so it is also available in SiteAdmin

The CQ.tagging.TagInputField provided two configuration parameter which won't work in combination:
tagsBasePath
namespaces
Using the OOTB facebook tags as example, I want to restric the dialog to only display the Favorite Teams. The Structure is this:
So I set tagBasePath to /etc/tags/facebook and namespaces to [favorite_teams]. This does what it is supposed to do and only shows the two teams in the dialog. But when you click on it, a JavaScript exceptions is thrown. The problem lies in the following method defined in /libs/cq/tagging/widgets/source/CQ.tagging.js
CQ.tagging.parseTag = function(tag, isPath) {
var tagInfo = {
namespace: null,
local: tag,
getTagID: function() {
return this.namespace + ":" + this.local;
}
};
// parse tag pattern: namespace:local
var colonPos = tag.indexOf(isPath ? '/' : ':');
if (colonPos > 0) {
// the first colon ":" delimits a namespace
// don't forget to trim the strings (in case of title paths)
tagInfo.namespace = tag.substring(0, colonPos).trim();
tagInfo.local = tag.substring(colonPos + 1).trim();
}
return tagInfo;
};
It does not respect the configurations set on the widget and returns a tagInfo where the namespace is null. I then overlayed the method in my authoring JavaScripts, but this is of course not working in the SiteAdmin as my custom JS are not included.
So, do I really have to overwrite the CQ.tagging.js below libs or can I somehow inject my overlay into the SiteAdmin so the PageProperties Dialog opened from there works as well?
UPDATE: I had a chat with Adobe support regarding this and it was pointed out that if you use tagsBasePath you need to place it somewhere else than below /etc/tags. But this won't work as well as the TagListServlet will return no tags as /etc/tags is also fixed in the TagManager as the tagsBasePath. I now overwrite the above mentioned js at its location, being well aware that I need to check it if we install a hotfix or an update. Is someone has a more elegant solution I'd be still thankful.

Free Shipping Cart rules aren't supported by socolissimoflexibilite (french carrier)

I'm trying to understand why the free shipping cartrule I just created doesn't work on all the available shipping methods.
I have one shipping method that becomes free, and the other (socolissimoflexibilite) doesn't change.
Could someone give me a hint, explanation, or some config/data/code to check on socolissimoflexibilite shipping method?
My first investigations lead me to the sales/quote_address_rate collection: one rate is well changed to 0.00€, but not the other.
I also checked the quote shipping address: its free_shipping field is set to 1.
Ok I found the answer :
We had a module (socolissimoflexibilite) extending the module socolissimosimplicite.
socolissimoflexibilite rewrites the collectRates() function, and freeShipping isn't supported anymore. I had to rewrite this part by myself.
For people getting the same issues with this module, here is the trick :
In Addonline_SoColissimoFlexibilite_Model_Carrier_ShippingMethod class, the collectRates() function must be replaced with this code :
public function collectRates(Mage_Shipping_Model_Rate_Request $request)
{
$rates = parent::collectRates($request);
$shippingAddress = Mage::getSingleton('checkout/session')->getQuote()->getShippingAddress();
if ($shippingAddress && $shippingAddress->getData('soco_product_code') == 'RDV') {
foreach ($rates->getAllRates() as $rate) {
if ($rate->getCarrier()===$this->_code) {
$rate->setPrice($rate->getPrice()+(int)Mage::getStoreConfig('carriers/socolissimoflexibilite/rdv_fees'));
}
}
}
if($shippingAddress->getFreeShipping()) {
foreach ($rates->getAllRates() as $rate) {
if($rate->getCarrier() === $this->_code) {
$rate->setPrice(0) ;
$rate->setCost(0) ;
}
}
}
return $rates;
}
And now, freeShipping rules will be supported by socolissimoflexibilite !

Trying to copy values into multiple embedded forms

I have a Symfony 1.4 application to allow users to enter data to a electrical appliance testing database. The page in questions consists of multiple embedded "new" forms so the user can submit many tests in one go. The form validates and saves correctly, but feedback is that it will be tedious to use.
As much of the data may be the same in each test (e.g. same date, same result, same person doing the testing), I would like the user to be able to fill in values in the top row, then click a button to fill the same information in the rows below. I'm pretty sure this would require javascript, but I don't have much experience.
I would appreciate any suggestions.
Many Thanks.
Well, I managed to figure it out without using javascript.
I put a button on the page
<input type="submit" name="copy_values" value="duplicate">
In the action for the page I included the code...
elseif (isset($_POST['copy_values'])) {
// get values from first embedded test
$newTests = $testList['new_tests'];
$testDate = $newTests[0]['et_date_tested'];
$testedBy = $newTests[0]['et_tester_id'];
$formOptions = array('test_date'=>$testDate, 'tester'=>$testedBy);
$this->form = new MultiTestForm(null, $formOptions);
}
$this->setTemplate('multiAdd');
... which takes the values from the widgets in the top row of the form and creates an array. This is passed as the options array to create a new form.
In the top level form class..
public function configure()
{
...
$subform = new sfForm();
for($i = 0;$i < sfConfig::get('app_new_test_rows'); $i ++)
{
$formToAdd = new TestsForMultiAddForm(null,$this->getOptions());
$subform->embedForm($i, $formToAdd);
}
$this->embedForm('new_tests', $subform);
}
...and in the embedded form class...
public function configure()
{
...
if ($this->getOption('test_date')) {
$this->setDefault('et_date_tested', $this->getOption('test_date'));
}
if ($this->getOption('tester')) {
$this->setDefault('et_tester_id', $this->getOption('tester'));
}
...
}
Not sure if this is the conventional way to approach the problem, but it works!

KRL and Yahoo Local Search

I'm trying to use Yahoo Local Search in a Kynetx Application.
ruleset avogadro {
meta {
name "yahoo-local-ruleset"
description "use results from Yahoo local search"
author "randall bohn"
key yahoo_local "get-your-own-key"
}
dispatch { domain "example.com"}
global {
datasource local:XML <- "http://local.yahooapis.com/LocalSearchService/V3/localsearch";
}
rule add_list {
select when pageview ".*" setting ()
pre {
ds = datasource:local("?appid=#{keys:yahoo_local()}&query=pizza&zip=#{zip}&results=5");
rs = ds.pick("$..Result");
}
append("body","<ul id='my_list'></ul>");
always {
set ent:pizza rs;
}
}
rule add_results {
select when pageview ".*" setting ()
foreach ent:pizza setting pizza
pre {
title = pizza.pick("$..Title");
}
append("#my_list", "<li>#{title}</li>");
}
}
The list I wind up with is
. [object Object]
and 'title' has
{'$t' => 'Pizza Shop 1'}
I can't figure out how to get just the title. It looks like the 'text content' from the original XML file turns into {'$t' => 'text content'} and the '$t' give problems to pick().
When XML datasources and datasets get converted into JSON, the text value within an XML node gets assigned to $t. You can pick the text of the title by changing your pick statement in the pre block to
title = pizza.pick("$..Title.$t");
Try that and see if that solves your problem.
Side notes on things not related to your question to consider:
1) Thank you for sharing the entire ruleset, what problem you were seeing and what you expected. Made answering your question much easier.
2) The ruleset identifier should not be changed from what AppBuilder or the command-line gem generate for you. Your identifier that is currently
ruleset avogadro {
should look something more like
ruleset a60x304 {
3) You don't need the
setting ()
in the select statement unless you have a capture group in your regular expression
Turns out that pick("$..Title.$t") does work. It looks funny but it works. Less funny than a clown hat I guess.
name = pizza.pick("$..Title.$t");
city = pizza.pick("$..City.$t");
phone = pizza.pick("$..Phone.$t");
list_item = "<li>#{name}/#{city} #{phone}</li>"
Wish I had some pizza right now!