- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
11-16-2014 02:06 PM
Hello Community,
I am creating a custom search on a UI Page. I have a single text box for input. After you type at least 3 characters, it triggers a timer for 2 seconds, then it automatically builds an encoded query using the search terms entered and runs that query to the sc_cat_item table against the meta fields to find related records using GlideAjax. The script creates <div> elements on the UI Page and sets the text inside of those DIVs to the name of the catalog items returned. There are a couple of problems I've run into so far..
1) I'm getting multiple queries running after the timeout period ends. If I typed "password" into the search, it will run the query 8 times (once for each letter) instead of just once for the word.
2) If I typed "password verizon", it will only return the records relevant to the term "password" instead of both terms.
3) Even using an Encoded Query, i'm not getting accurate search results. If I create a GlideRecord query using the 'Background Scripts' module, and insert the same encoded query, i get accurate results. When it runs via GlideAjax on the UI Page, i don't get the same results.
The script that i'm using is a simple GlideRecord query...
var ir = new GlideRecord('sc_cat_item');
ir.addEncodedQuery('metaLIKEpassword^ORmetaLIKEverizon');
ir.query();
while(ir.next()){
return ir.name;
}
Any suggestions on any of these problems?
Solved! Go to Solution.

- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
11-21-2014 10:39 PM
Hi Kenneth,
I can't see anything immediately wrong with your ajax function, except that _getUserGroups() has no return value. Try adding the following statements in red text.
getUserGroups: function(myUser){
myUser = this.getParameter('sysparm_user');
gs.log('getUserGroups() parameter myUser: '+myUser);
return this._getUserGroups(myUser);
},
_getUserGroups: function(myUser){
gs.log('_getUserGroups() parameter myUser: '+myUser);
var gr = new GlideRecord('sys_user_grmember');
gr.addQuery('user',myUser);
gr.query();
gs.log('_getUserGroups() getRowCount(): '+gr.getRowCount());
var groupsArray = [];
while(gr.next()){
//gs.log("SCRIPT INCLUDE :" + gr.group);
groupsArray.push(gr.group.sys_id.toString()); // collect sys_id values in array of string values
}
gs.log('groupsArray: '+groupsArray.toString());
return groupsArray.toString();
}
Check that all of the log statements make it to the system log. Confirm the row count value as this will tell you how many results were returned by the query, and then check the final log statement, which should be a comma separated list of sys_id values (the same number as the row count etc). After the final log statement, I've added a return statement which should return the comma separated string of sys_id values, to the first function (getUserGroups()). That function should return the value to your client side function.
Regards,
Jake

- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
11-16-2014 02:50 PM
Hi Kenneth,
Regarding your points:
1) The timing can be tricky. Are you using the "onkeyup" event to trigger your timer/AJAX script? If so, you may need it to check if there is a query already running, then set a flag to ignore the AJAX result when it comes back, to make way for the new result being requested. Without seeing your code, it sounds like the timer is not being reset correctly each time the "onkeyup" event is triggered. Each event should restart the timer, and only when the timer hits its nominated period (e.g 2 sec), should it initiate the AJAX request.
2) Once again, without seeing your code I'm not sure why the second word is being ignored, but it's either not being added to your encoded query, or being added incorrectly.
3) As per (2), you may need to check how you are building the encoded query term. In your example glide query from the background script, I can see you've added 2 "contains" searches (one for each term) with an "or" operator between them. Is this the same syntax you're building for your AJAX query? I would build the encoded query as a string variable first, and send it to a log statement to confirm it matches your test script, before running the query. It could be something as simple as missing the ^ symbol before the OR operator etc. To build the encoded query in the same way as your test script, you would have to split the search term string into an array (use .split(" ") to split on the spaces), then use "fieldLIKEterm1" for the first term, and "^ORfieldLIKEterm2" for each subsequent term, to ensure they are properly "OR'd".
Regards,
Jake
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
11-16-2014 03:17 PM
Here is what my script looks like so far. It's been changed since I was troubleshooting but I think this is close to what I had originally..
The input box...
<input id="stextbox" type="text" placeholder="Search..." required="true" onkeydown="clearTimeout()" onkeyup="startSearch()"></input>
The onkeyup function...
function startSearch(){
var string = gel("stextbox").value;
if(string.length > 3){
setTimeout(function(){
var words = gel("stextbox").value;
var searchTerms = words.replace(/ /g,"^ORmetaLIKE")
jslog(searchTerms);
var ga = new GlideAjax("SuperSearchUtils");
ga.addParam('sysparm_name','findMetaStuff');
ga.addParam('sysparm_meta_search', searchTerms);
ga.getXML(findMetaStuffParse);
},2000);
}
}
The callback function..
function findMetaStuffParse(response){
var answer = response.responseXML.documentElement.getAttribute("answer");
jslog(answer);
}
The HTML to create new DIV elements for results...(in the callback function)
var newParent = document.getElementById('dynamicstuff');
var newChild = document.createElement('div');
var existingChildren = document.getElementById('dynamicstuff').childNodes;
/*for(r=0; r < existingChildren.length; r++){
if(existingChildren[r].innerHTML == results){
return false;
}
}*/
newChild.id = 'result';
newChild.innerHTML = results;
newParent.appendChild(newChild);
This is the function being called in the Script Include via the GlideAjax above(findMetaStuff)...
NOTE: I am aware this function isn't currently doing anything to yield me better results. This is a heavily modified version of what I had and is very much under construction. The goal was to find the indexOf the comma that was inserted by using the .split() and then use substring to create individual search terms and run those individually to see if I got different results.
findMetaStuff: function(){
var words = this.getParameter('sysparm_meta_search').toString();
var findFirstComma = words.indexOf(",");
var searchTermOne = words.substring(0,findFirstComma);
var findSecondComma = words.indexOf(",",findFirstComma+1);
var searchTermTwo = words.substring(findFirstComma,findSecondComma);
return words;
/*var items = new GlideRecord('sc_cat_item');
items.addEncodedQuery(this.getParameter('sysparm_meta_search'));
items.query();
while(items.next()){
return items.name;
}*/
},

- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
11-16-2014 03:55 PM
Hi Kenneth,
Just a couple of things to check:
1. Missing ; on line: var searchTerms = words.replace(/ /g,"^ORmetaLIKE")
2. Since you're sending this string via XML, I would avoid using any special characters in your searchTerms string. Try sending the original string value (less any special characters - only leave spaces and letters etc) back to your Script Include function. There you can build the encoded query string and log it using gs.log, just before you use it in the .addEncodedQuery() line.
3. I'm a bit lost with the structure of the searchTerms string between your client script function "startSearch()" and your script include function "findMetaStuff". The client script builds the search terms into an encoded query (using ^OR and LIKE etc), but your script include is expecting a comma separated string? As I mentioned above, I would send back the original input text (with special characters removed), so your script include should receive string with (potentially) multiple words, separated by spaces. Then you could use .split(" ") to separate these into an array for processing (or you could use the regex you've used in the client script above. You need to make sure that the encoded query string that is being used in your script include function, matches that of your test script, to confirm the same results. If they are the same, then I would log an array of the returned record sys_ids to gs.log (from your script include function), to then check if the issue is between the glide query and the custom html that builds the <div> results.
Regards,
Jake
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
11-21-2014 02:40 PM
I got something separate that I'm working on but it's going down this same route and now i seem to have a slightly opposite problem. I'm only getting one record back when I need multiple records. I tried using the gs.log in the Script Include but it only writes this to the log when I try...
syslog_transaction not found for AjaxClientTiming: sysId: , table: , view: Default view, form: ui_page_render
Here are the other 2 functions i'm using from the same Script Include...
getUserGroups: function(myUser){
myUser = this.getParameter('sysparm_user');
return this._getUserGroups(myUser);
},
_getUserGroups: function(myUser){
var gr = new GlideRecord('sys_user_grmember');
gr.addQuery('user',myUser);
gr.query();
while(gr.next()){
gs.log("SCRIPT INCLUDE :" + gr.group);
}
}