Keyword highlighting after a find

Release notes for Servoy betas

Keyword highlighting after a find

Postby david » Mon Jun 02, 2003 10:10 pm

Anyone figured out a way to highlight search words in a found set?

- david
User avatar
david
 
Posts: 1727
Joined: Thu Apr 24, 2003 4:18 pm
Location: Washington, D.C.

Postby Jan Aleman » Tue Jun 03, 2003 12:03 am

pretty easy. Make sure to store the find string (=highight text) in a global. In this example I will call it search_string. In this example the search is done in one field that in this example I have called testplain. After search is done redirect the user to a form on which you have placed the following calculation field with display type html:

Code: Select all
var re = eval("/" + globals.search_string + "/gi");
return "<html>" + testplain.replace(re,"<b>"+globals.search_string+"</b>")+"</html>";


Don't be scared about the regular expression I use to do the replace, its pretty straight forward and in the 1.1 release we will have a new node with an easier to understand replace function.

Basicly here is what happens:
We construct a regular expression re that contains our global variable search_string and the instructions for a global (g) and ignore case (i) replace. In the .replace function we apply this regular expression while adding the html tags so an html calc results. The result of this calculation is that whatever is in the global field search_string will be displayed bold in your result field.[/b]
Jan Aleman
Servoy
Jan Aleman
 
Posts: 2083
Joined: Wed Apr 23, 2003 9:49 pm
Location: Planet Earth

Postby david » Tue Jun 03, 2003 12:29 am

Way cool. I was thinking that "if only I could format a field using HTML" it would be a relatively simple task....

- david
User avatar
david
 
Posts: 1727
Joined: Thu Apr 24, 2003 4:18 pm
Location: Washington, D.C.

Postby Jan Aleman » Tue Jun 03, 2003 1:00 am

It is pretty cool!, even I like it and I'm not easily impressed 8)

I just got a note from one of our javascript gods that I was using eval incorrectly. I understood that although it will work in most cases things could go wrong if a slash is involved in the search criteria. The correct syntax is:

Code: Select all
var re = new RegExp(globals.search_string, "gi");
return "<html>" + testplain.replace(re,"<b>"+globals.search_string+"</b>")+"</html>";


in the above instead of evaulating the result of an expression we are creating a new regular expression using the regular expression constructor.
Jan Aleman
Servoy
Jan Aleman
 
Posts: 2083
Joined: Wed Apr 23, 2003 9:49 pm
Location: Planet Earth

Re: Keyword highlighting after a find

Postby BulldogBen » Sun Jul 04, 2010 4:39 pm

Great code, makes the user's experience much nicer when looking through search results.

I have two further questions...

1) Is there a way to ensure even if search is lowercase that result is displayed as-was (see screenshot where Mrs taylor is shown, whereas the name_first field actually contains Mrs Taylor?

2) What's the best way to apply this code to many fields without too much re-writing? Do I really need to create a calculation field to mirror every field I want to search on (which eventually will be about 10 fields)? See screenshot of how I would like to end-up, in this case I've manually coded for name_first and name_last.

The way I perform my search is...
Code: Select all
function performSearch(event) {
   // Performs sub-string search on person
   var s = '%' + globals.search_string + '%';

   // Clear results and find by first name
   controller.find();
   name_first = s;
   controller.search(true,false);
   
   // Add surname results to search
   controller.find();
   name_last = s;
   controller.search(false,false);

   // etc
   controller.find();
   business = s;
   controller.search(false,false);
   
   controller.find();
   email_1 = s;
   controller.search(false,false);
   
   // Takes focus back to search box so user can modify search immediately
   elements.searchBox.requestFocus(false);
}
Attachments
screenshot.jpg
desired search results screenshot (well, almost, I'd like to show Taylor not taylor
screenshot.jpg (29.09 KiB) Viewed 24460 times
27" iMac, MacOS 10.6.4
Servoy 5.2 / SQL Anywhere 11
Java 1.6.0_20
User avatar
BulldogBen
 
Posts: 58
Joined: Sun Jun 20, 2010 1:02 pm

Re: Keyword highlighting after a find

Postby ptalbot » Mon Jul 05, 2010 12:49 am

Hi Ben,

for 1/ RegExp has a way to capture the matched String using parenthesis, so you can do this:
Code: Select all
var re = new RegExp("("+globals.search_string+")", "gi");
return "<html>" + testplain.replace(re,"<b>$1</b>")+"</html>";

the $1 in this case will be replaced by the 'captured' String.

for 2/ if you do it for each field, you will need to have a calculation, but perhaps you could build your own html table, I believe that would be more efficient.

Finally, I noticed that you are issuing a lot of searches to get your results.
You could do:
Code: Select all
if (controller.find()) { // don't forget to test if you are allowed to search
   name_first = s;
   controller.newRecord();
   name_last = s;
   controller.newRecord();
   // etc.
   controller.find();
}

because when you are in find mode, each time you issue a newRecord (on controller, or foundset), Servoy actually inteprets it as a new OR clause, so the resulting SQL will be something like
Code: Select all
SELECT * FROM yourtable WHERE name_first = ? OR name_last = ? OR ...

and this will hit the database only once.

Now actually, what we tend to do for searches on many fields, is to build a view with a concatenation of the searched fields, and search on this one only, which allow us to issue only one SELECT query without any OR clauses (OR clauses are not very optimal most of the time). We found it more efficient this way.
Patrick Talbot
Freelance - Open Source - Servoy Valued Professional
https://www.servoyforge.net
Velocity rules! If you don't use it, you don't know what you're missing!
User avatar
ptalbot
 
Posts: 1654
Joined: Wed Mar 11, 2009 5:13 am
Location: Montreal, QC

Re: Keyword highlighting after a find

Postby BulldogBen » Sun Jul 11, 2010 3:38 pm

This works really well, I've now got a question about making my code more general?. So far I've done this with two fields, and the code is almost identical for each as you can see below.

Code: Select all
function name_last_disp()
// Used for highlighting the search string in the results field
{
   if(name_last != null)
   {
      var re = new RegExp("("+globals.search_string+")", "gi");
      return "<html>" + name_last.replace(re,"<b>"+globals.search_string+"</b>")+"</html>";
      }
   }

function name_first_disp()
// Used for highlighting the search string in the results field
{   
   if(name_first != null)
   {
      var re = new RegExp("("+globals.search_string+")", "gi");
      return "<html>" + name_first.replace(re,"<b>$1</b>")+"</html>";
   }
}

How can I generalise this calculated field code so I can use the same code in each field for which I want highlighted results?
27" iMac, MacOS 10.6.4
Servoy 5.2 / SQL Anywhere 11
Java 1.6.0_20
User avatar
BulldogBen
 
Posts: 58
Joined: Sun Jun 20, 2010 1:02 pm

Re: Keyword highlighting after a find

Postby ptalbot » Sun Jul 11, 2010 6:34 pm

You could define a global function like this:
Code: Select all
function hilite(what)
// Used for highlighting the search string in the results field
{
   if(what != null)
   {
      var re = new RegExp("("+globals.search_string+")", "gi");
      return "<html>" + what.replace(re,"<b>$1</b>")+"</html>";
   }
   return what;
}


then call it from your calcs this way:
Code: Select all
function name_last_disp()
{
    return globals.hilite(name_last);
}

function name_first_disp()
{
    return globals.hilite(name_first);

}
Patrick Talbot
Freelance - Open Source - Servoy Valued Professional
https://www.servoyforge.net
Velocity rules! If you don't use it, you don't know what you're missing!
User avatar
ptalbot
 
Posts: 1654
Joined: Wed Mar 11, 2009 5:13 am
Location: Montreal, QC

Re: Keyword highlighting after a find

Postby BulldogBen » Sun Jul 11, 2010 10:50 pm

Wow, as easy as they hey, just a simple function with a sting passed in, thanks for pointing me in the right direction.

Let's take it a step further. If I have many fields on a form, each with a text label, and I want clicking the text label to do essentially the same thing, is there any way to reference the field name the text is associated with and pass that into a single method?

If that can't be done, could I intercept the right click event on the field and get the field name that way to pass into my totally general method?

Hope the question makes sense, just don't want to write the same code 10 times putting different field names in each time + I'm sure there's a great general lesson to be learnt.
27" iMac, MacOS 10.6.4
Servoy 5.2 / SQL Anywhere 11
Java 1.6.0_20
User avatar
BulldogBen
 
Posts: 58
Joined: Sun Jun 20, 2010 1:02 pm

Re: Keyword highlighting after a find

Postby ptalbot » Sun Jul 11, 2010 11:35 pm

BulldogBen wrote:Wow, as easy as they hey, just a simple function with a sting passed in, thanks for pointing me in the right direction.

Let's take it a step further. If I have many fields on a form, each with a text label, and I want clicking the text label to do essentially the same thing, is there any way to reference the field name the text is associated with and pass that into a single method?

If that can't be done, could I intercept the right click event on the field and get the field name that way to pass into my totally general method?

Hope the question makes sense, just don't want to write the same code 10 times putting different field names in each time + I'm sure there's a great general lesson to be learnt.

You could take advantage of the JSEvent object which is passed automatically as the first parameter of all the event driven methods...

If you create a form method by attaching it to one of the events, like onAction, onDataChange, onRightClick, you will see that the first parameter in the method created is called "event" and it is of a type JSEvent:
Code: Select all
/**
* Perform the element default action.
*
* @param {JSEvent} event the event that triggered the action
*
*/
function onAction(event) {
   globals.doSomeGenericStuff(field);
}

You can ask this object for the name of the form, and of the field, using event.getFormName() and event.getElementName(), you can also ask for the source object of the event, here are some starting points:
Code: Select all
function doSomeGenericStuff(event) {
    var frm = forms[event.getFormName()];
    var field = event.getSource();
    var value = forms[event.getFormName()].foundset.getDataProviderValue(field.getDataProviderID());
    // etc..
}

Have a look at the JSEvent Object properties and events (under 'Application > JSEvent' in the Solution Explorer view, and you will get some ideas.
Patrick Talbot
Freelance - Open Source - Servoy Valued Professional
https://www.servoyforge.net
Velocity rules! If you don't use it, you don't know what you're missing!
User avatar
ptalbot
 
Posts: 1654
Joined: Wed Mar 11, 2009 5:13 am
Location: Montreal, QC


Return to Latest Releases

Who is online

Users browsing this forum: No registered users and 8 guests

cron