Gossamer Forum
Home : Products : DBMan : Customization :

sorting radio fields contd.

(Page 1 of 2)
> >
Quote Reply
sorting radio fields contd.
I've reconsidered the problem I posted earlier on, about sorting radio fields. Note that I'm not at all good at perl, so apologies if some of my problems are all too primitive.

What I want to do: A bibliography database should, for each entry, contain the information whether it is an article or a book. So I have devised a field "category", as a radio field with the options "article" and "book".
When a user searches the database by the field "name", search results should be printed as follows:
"These are the publications by "name"
Articles:
(Here follows a list of individual articles, sorted ascending by field "year")
Books:
(Here follows a list of individual books, also sorted ascending by field "year")"

Problems/Questions:
- How do I add code that makes dbman check on whether the search results contain entries where "$rec{'category'} eq "article"", and if so, print the heading "Articles:", and do so only ONCE? If I add something like "if ($rec{'category'} eq "article") {print qq|Articles:|;}", then I get the heading for EACH article result individually, but not for the entire section of articles. I guess the "for (0 .. $numhits - 1) {&html_record (&array_to_hash($_, @hits));}" in sub html_view_success is responsible for this, but don't know what to change.

- If "sort ascending by field "year"" is specified in the search-form, will dbman then sort ALL results by year (which I fear will be the case), and do I have to use the multiple sort mod in order to have it sort first by category, then by year? Plus: If I let dbman sort by category, where the values can be "article", "book" and "translation", is there a way to specify a sorting sequence which is neither ascending nor descending, like "book" > "translation" > "article"?

as usual - many thanks in advance,



kellner
Quote Reply
Re: sorting radio fields contd. In reply to
Please visit the FAQ noted below and check under "Viewing". There are some posts such as:
"Layered displays", "Displaying a Field's Title Only Based on Contents", and "Adding a category specific message in results page for the chosen category" which are posts which may give you ideas, but I'm sure if you check some of the other threads noted, you may find other possibilities also.

There's also one for a Multi-tier category list which may apply to what you are trying to do.

Hope this helps

Unoffical DBMan FAQ
http://webmagic.hypermart.net/dbman/
Quote Reply
Re: sorting radio fields contd. In reply to
Thanks, Lois C. I implemented the multiple search mod, and it seems to work fine.
I still haven't found a solution to my display problem. None of the threads I browsed in the "view" section of the FAQ seems to contain info on how to determine whether the %rec hash at all contains a particular value in a certain field, and if so, print a *generic* header for all values where this is true.

At the risk of repeating myself:
If I add the conditional "if ($rec{'category'} eq "article") {print qq|These are all articles by $rec{'name'}:|;}", then I get something like the following:

"These are all articles by Some Author:
Author, Some (1982): "This is my first article." Journal 12, 1-15.
These are all articles by Some Author:
Author, Some (1987): "This is my second article." Journal 14,15-30."

What I want to get is however:
"These are all articles by Some Author:
Author, Some (1982): "This is my first article." Journal 12, 1-15.
Author, Some (1987): "This is my second article." Journal 14,15-30."

A possible approach could be as follows:
1) Determine whether %rec contains the value "article" in the field "category" at all, i.e. whether there is at least one instance where "$rec{'category'} eq "article"". How do I code such a condition? If it is fulfilled, print out the generic header for this category. If not, proceed to the next value of the field category, i.e. check whether there is at least one instance where "$rec{'category'} eq "book"".
2) After having printed the generic header, for each result where "$rec{'category'} eq "article"", print out the data. This seems relatively easy: "foreach ($rec{'category'} eq "article") {print qq|Here comes the code to print the individual results.|;}"
3) Go back to 1) and start again with the condition "if there is at least one instance where $rec{'category'} eq "book"", etc.

Note: Searches are restricted to the "name"-field in this routine, so the output will contain only entries with the same value in this field. The sort order is set to 2) category (ascending) and 3) year (ascending), so I suppose that the above routine would print out data for each category sorted by year.

Now I only need to find out how to write the code for step 1) ...


kellner
Quote Reply
Re: sorting radio fields contd. In reply to
Have you implemented the multiple sort mod? Is it working for you?

JPD
http://www.jpdeni.com/dbman/
Quote Reply
Re: sorting radio fields contd. In reply to
Yes, JPDeni, the multiple sort mod works fine - as far as I can determine, given that I still have output formatting problems. Which are my main concern at the moment.
Currently I'm wondering how to access search results in html_view_success, because I think the easiest way to achieve what I want (see above) seems like:
1) Check whether the search results contain at least one instance where the field "category" has the value "article". This command as well as steps 2) and 3) should be coded into sub html_view_success,
2) If so, print out the heading "Articles by $in{'name'}:<BR>". If not, move on to 3).
3) For each search result where the field "category" has the value "article", &array_to_hash; &html_record_article. This should pass on the results to sub &html_record_article which then prints out a list of all results as an unnumbered list.
4) Check whether there is at least one instance in the search results where the field "category" has the value "book".
5) If so, print out heading "Books by $in{'name'}:<BR>"
6) For each search result where "category" has the value "book", &array_to_hash; &html_record_book. As in 3), this should produce an unnumbered list of all the results in this category.

I think the structure is clear enough, though I don't know enough perl to understand the implications of it. I don't know exactly what array_to_hash does, for instance, but it seems to be necessary to call it in order to have html_record, for which I created two variants depending on which category the search result is in, do what it is supposed to do.
My main problem lies in what is printed in red above. I know that in html_view_success, search results are accessable in @hits. But how do I access values of specific fields that are stored in there? If that's impossible, an alternative way might be to use an expression that is certain not to occur anywhere else in @hits - like "##article##" - for category information, and to then simply check whether this expression occurs in @hits. Though I don't know how to code that either.

Any help will be greatly appreciated, and best wishes to JPDeni's back,

kellner
Quote Reply
Re: sorting radio fields contd. In reply to
The thing is that, if the multiple sort works, and you're sorting first by "category" and then by "date," you should come up with the following order:

Article -- 1965
Article -- 1970
Article -- 1975
Article -- 1983
Book -- 1967
Book -- 1989
Book -- 1997
Translation -- 1962
Translation -- 1965
Translation -- 1984

Right?

If that's what you're getting, then all you need to do is to check to see if the next record has the same value in the category field as the previous one did. If it doesn't, then print out a header.

Before I write the code for this, I want to be sure that the sort order I'm assuming is correct and that this is what you want.

You mentioned earlier about "sorting" but not alphabetically -- Book, Translation, Article. There's only one way I can think of to do this -- well, actually two ways. The first way would be to have another field with the sort order. Book would have a "1" in the field, Translation would have a "2" and Article would have a "3." It could pretty easily be done without your having to manually enter the values. The other way would be to stick the numbers at the beginning of the categories -- 1Book, 2Translation, 3Article. Then it would sort the way you want. You could chop off the first character when you print it out so the numbers wouldn't be seen. You could even have the stick the numbers in so you wouldn't have to do it.

I really don't think that searching through all the results is the way to go. It's pretty complicated and if the script will put the records in the correct order by itself, there's no need to reinvent the wheel. Smile

JPD
http://www.jpdeni.com/dbman/
Quote Reply
Re: sorting radio fields contd. In reply to
You are right, the sort order is 1) category, 2) year.
On that approach, the whole thing would turn out as follows:
1) Check the value for category of the first record. Print out header accordingly.
2) Check the value for category of the next record. If it is the same as that of the first record, print out the record data, but no header. If it is different from that of the first record, print out header accordingly.
3) Repeat until all records have been checked.

As far as sorting is concerned, adding numbers to the beginning of category values seems allright to me. Since these values need not be printed in the output anyway - the headings don't have to contain the values -, I don't even think it would be necessary to chop off the numbers. One question though: If I define the field category as alpha, will the sort routine then still sort according to the first *number* of the value? If I define it as numerical, would that allow the rest of the value after the first character to be alpha? It would be possible to just have the numbers anyway; having the values as "book", "article" or "translation" only makes the database more understandable to me.

Thanks a lot for helping to free the world from even more wheel-inventors,






kellner
Quote Reply
Re: sorting radio fields contd. In reply to
In Reply To:
Thanks a lot for helping to free the world from even more wheel-inventors,
Laugh Well, a lot of this comes from several years of working with the script. And I did something like this before for someone else.

In Reply To:
One question though: If I define the field category as alpha, will the sort routine then still sort according to the first *number* of the value?
Yep. It would only cause problems if you had a whole lot of categories. 'alpha' will sort 1, 2, 3 correctly, but if you had, say 11 categories, it would sort them 1, 10, 11, 2, 3.... As long as you have less than 9 categories, it's no problem. (However, if you ever wanted to add categories that you wanted to sort in between, you could take advantage of this. Say you wanted to add a "Pamphlet" category, which you wanted to come out after the "Books." Just set the number for "Pamphlets" to 10.)

In Reply To:
It would be possible to just have the numbers anyway; having the values as "book", "article" or "translation" only makes the database more understandable to me.
You could have it translate the values when a record is added. That wouldn't be hard at all.

Okay. Now for the code.

In sub html_record, after

my (%rec) = @_;

add

Code:

if ($rec{'Category'} ne $prev_cat) {
$prev_cat = $rec{'Category'};
print qq| all of your heading stuff|;
}
Pretty simple, huh? Smile Be sure to change Category to match the *exact* name of your field.

JPD
http://www.jpdeni.com/dbman/
Quote Reply
Re: sorting radio fields contd. In reply to
VERY simple - alas, too simple for me to actually understand it. I thought to use it as follows:

if ($rec{'category'} ne $prev_cat) {
$prev_cat = $rec{'category'};

as I understand it, this first checks whether the value of "category"
is different from the value of $prev_cat. What this actually does
for the first result, I don't know.
For the other results, if the condition is true (i.e. new value for cat.), then
set the value of prev_cat the current value of cat. This is clear.

if ($rec{'category'} eq "article") {
here starts the condition for what to do when cat=article in case it's the first occurrence of this value.
print qq| <h2>Articles by $rec{'firstname'} $rec{'lastname'}:</h2><ul><li>|;
print header
&html_record_article; call sub for printing out the actual search results.
}
elsif ($rec{'category'} eq "review") {

next alternative: if cat=review, and if this is the first
occurrence of review - same structure as above.
print qq| <h2>Reviews by $rec{'firstname'} $rec{'lastname'}:</h2><ul><li>|; print header
&html_record_review;
}
}
else {

meaning: if "$rec{'category'} eq $prev_cat" returns false, i.e. if the current value of cat is the
same as the previous one. in this case, print out results without heading for each category
print qq|<li>|;
if ($rec{'category'} eq "article") {
&html_record_article;
}
elsif ($rec{'category'} eq "review") {
&html_record_review;
}
}
}


For some reason, the program doesn't move from the initial "if" to the subsequent "else" - i.e. the process to be initialized when the condition is false does not take place.


kellner
Quote Reply
Re: sorting radio fields contd. In reply to
In Reply To:
What this actually does for the first result, I don't know.
For the first result, there is nothing in $prev_cat, so $rec{'category'} will not be equal to $prev_cat. (Assuming, of course, that the "category" field is a required field.)

I notice in your code that you have an extra } at the end. It could be that you just copied the ending bracket for the subroutine, but I wanted to be sure.

Am I correct that your code, sans comments, looks like

Code:

if ($rec{'category'} ne $prev_cat) {
$prev_cat = $rec{'category'};
if ($rec{'category'} eq "article") {
print qq| <h2>Articles by $rec{'firstname'} $rec{'lastname'}:</h2><ul><li>|;
&html_record_article;
}
elsif ($rec{'category'} eq "review") {
print qq| <h2>Reviews by $rec{'firstname'} $rec{'lastname'}:</h2><ul><li>|;
&html_record_review;
}
}
else {
print qq|<li>|;
if ($rec{'category'} eq "article") {
&html_record_article;
}
elsif ($rec{'category'} eq "review") {
&html_record_review;
}
}
Seems like it should work.

Here's another way to acheive the same result. (This is some fancy coding, but it works. Smile)

Code:

if ($rec{'category'} ne $prev_cat) {
$prev_cat = $rec{'category'};
$title = ucfirst($rec{'category'}) . "s";
print qq| <h2>$title by $rec{'firstname'} $rec{'lastname'}:</h2><ul>|;
}
print qq|<li>|;
eval "html_record_$rec{'category'}";
The advantage of this (besides being smaller) is that, if you later added more categories, you wouldn't have to change the code. You'd just have to create a new subroutine for the category.

JPD
http://www.jpdeni.com/dbman/
Quote Reply
Re: sorting radio fields contd. In reply to
Two problems remain, and one even fancier option pops up Tongue(do they *ever* stop?):

1) I use the compact code you wrote (great!). I get get the headers printed out ok, but the subs for the respective search result printout are still not called (or "evaluated").
These subs now look like this:
sub html_record_article { ("article" is the value of $rec{'category'})
print qq|this is your search result.|;
&html_record_end; }
;
And sub html_record_end looks like this:
sub html_record_end {
print qq|this is some final text for all categories. </li></ul>|;}


2) You mentioned that "category" had to be a required field for "if ($rec{'category'} ne $prev_cat)" to work. Question: If it's not required, but if there will in practice always be a value for $rec{'category'}, will the condition still work? Otherwise, if I make "category" required, combined category returns become impossible. Or maybe they are possible if I use checkboxes instead of radio boxes.

3) Fancier option: If I don't want $title to be based on the value of $rec{'category'}, could I somehow add subs with fancier heading text and call them, er, but how?

Sorry for taking up so much of your time,

kellner
Quote Reply
Re: sorting radio fields contd. In reply to
I think I'm going to need to see your whole html.pl file. What you posted looks fine, but there could be something else that's not obvious which is causing the problem.

In Reply To:
2) You mentioned that "category" had to be a required field for "if ($rec{'category'} ne $prev_cat)" to work. Question: If it's not required, but if there will in practice always be a value for $rec{'category'}, will the condition still work? Otherwise, if I make "category" required, combined category returns become impossible. Or maybe they are possible if I use checkboxes instead of radio boxes.
I'm not sure I understand. But, yes, as long as you can guarantee that there will always be an entry in the field *and* that there will always be a matching subroutine for that entry, everything will be fine.

I may be misreading what you wrote above, but I need to be sure. You're not having multiple selections possible for the field, are you? If so, we need to start from scratch. Smile

In Reply To:
3) Fancier option: If I don't want $title to be based on the value of $rec{'category'}, could I somehow add subs with fancier heading text and call them, er, but how?
What would you want them based on?

In Reply To:
Sorry for taking up so much of your time,
SmileNo problem.


JPD
http://www.jpdeni.com/dbman/
Quote Reply
Re: sorting radio fields contd. In reply to
In Reply To:
I think I'm going to need to see your whole html.pl file. What you posted looks fine, but there could be something else that's not obvious which is causing the problem.
OK, it's quite long though (854 lines, most of them redundant no doubt), should I email it to you?
In Reply To:
It may be misreading what you wrote above, but I need to be sure. You're not having multiple selections possible for the field, are you? If so, we need to start from scratch.
No, I think I confused (a) having a field required = there must be a value for this field in all database entires and (b) restricting search input to that field. Anyway, it's not a problem. However, as things are now, I get an error message saying "no search terms specified" when I search the db on the "lastname" field WITHOUT checking one of the category radio boxes. This suddenly turned up just now. I assume that this error has to do with the multiple sort mod, but am not sure.
In Reply To:
What would you want them based on?
I was thinking of a sub like this:
sub html_record_article_title {#this could be html_record_$rec{'category'}_title
print qq~Oh mighty user $rec{'name'}! These are all your articles:~;}
So perhaps I could just use:
if ($rec{'category'} ne $prev_cat) {
$prev_cat = $rec{'category'};
&html_record_$rec{'category'}_title;
}
print qq|<li>|;
eval "html_record_$rec{'category'}";



kellner
Quote Reply
Re: sorting radio fields contd. In reply to
In Reply To:
OK, it's quite long though (854 lines, most of them redundant no doubt), should I email it to you?
No. Copy it to a web-accessible directory -- one where you would place .html files -- and rename it to html_pl.txt. Then come back and give me the URL and I'll go pick it up.

Regarding your other code, you would have to use

eval "html_record_$rec{'category'}_title";

You can't just use a subroutine call if you have a variable in the subroutine name. (I tried it. I got a syntax error. Smile)

You certainly can do that if you wish. I'm always one for having code as compact as possible and I hate repeating things if I don't have to. If your titles were to be completely different, depending on the category, this would be the way to go. Otherwise, I would try to just have one title with variables.

A lot of it is differences in programming style, though. Smile

With your search problem, you may be right about it being related to the multiple sort. I haven't worked with the multiple sort mod at all, so I'm not even sure how it works.

JPD
http://www.jpdeni.com/dbman/
Quote Reply
Re: sorting radio fields contd. In reply to
You can access the html-file at http://www.univie.ac.at/itb/biblhtml.txt.
Though I think I solved the problem. Instead of eval "html_record_$rec{'category'}", use "eval "html_record_&rec{'category'}(%rec)" - the same goes for the other subs that are called from html_record, as of course the values must be passed on! Then also add my (%rec) = @_; at the beginning of all the subs that are called from within html_record, and there you are.
The only thing that remains now is that I have to find out how to terminate the unnumbered list. The way the code runs now, the list is terminated after the first result of a category. When there is a second result, no new list begins because no header is printed. Perhaps I have to use an if/else-conditional to code this, but I'm too tired now.

The search problem also resolved itself - it was really stupid; I had renamed some field-names in the config file and forgotten to upload it!

cheers,

kellner
Quote Reply
Re: sorting radio fields contd. In reply to
In Reply To:
the values must be passed on!
Right. I hadn't thought about that.

If it's working, I don't need to see the file. Smile

In Reply To:
The way the code runs now, the list is terminated after the first result of a category.
I'm having a hard time picturing this.

JPD
http://www.jpdeni.com/dbman/
Quote Reply
Re: sorting radio fields contd. In reply to
In Reply To:
I'm having a hard time picturing this.
The code looks like this now:
my (%rec) = @_;
($db_auto_generate and print &build_html_record(%rec) and return);
#do I really need this line?

if ($rec{'category'} ne $prev_cat) {
$prev_cat = $rec{'category'};
print qq|<h2>|;
eval "html_record_$rec{'category'}_title(%rec)";
print qq|</h2><ul>|;
}
print qq|<li>|;
eval "html_record_$rec{'category'}(%rec)";
&html_record_end(%rec);
print qq|</ul>|;
}

If the record is the first one of its category, the sub prints the heading plus <ul>. If not, it doesn't.
In both cases, the sub then prints the search results (the </li>-tag is contained in sub html_record_end).
As it stands now, the sub then also prints </ul>. If there's only one record for category "article", this is just as well. If there's a second record, the sub will, without printing the heading (that contains the <ul>-tag), still print a </ul> at the end.
I know that this is stupid, but don't know what to change. I suppose some code that checks whether the next record has the same value in $rec{'category'} as the current one would be needed at the very end: If so, don't close the list; if not, close it.
Or maybe a loop in the beginning: If this is the first search result, print heading. If it isn't, and if ($rec{'category'} ne $prev_cat), print </ul> plus the heading.



kellner
Quote Reply
Re: sorting radio fields contd. In reply to
Now I understand. (I am a little slow sometimes. Smile)

Easy fix.

Delete the line -- print qq|</ul>|;

After if ($rec{'category'} ne $prev_cat) { -- add

if ($prev_cat) { print qq|</ul>|; }

This will cause the closing of the list only when a new category starts.

You will also want to put print qq|</ul>|; in sub html_view_success, after the "for" loop that prints out the records. I'm not sure exactly what yours looks like by now, but if you had the default code, it would be

Code:

for (0 .. $numhits - 1) {
print "<P>";
&html_record (&array_to_hash($_, @hits));
}
print qq|</ul>|;
This would close off the last one.

You were definitely on the right track with your idea. Smile


JPD
http://www.jpdeni.com/dbman/
Quote Reply
Re: sorting radio fields contd. In reply to
I did what you suggested, and it works like a charm. Wonderful! Thanks for your prolongued assisctance throughout this thread!
I am considering writing a mod based on what I've learnt because I think that a number of people might want to adapt DBMan to this situation, i.e. to have DBMan sort according to categories and then display ordered lists of search results.

kellner
Quote Reply
Re: sorting radio fields contd. In reply to
Cool! We can use some more mods in the Resource Center.

Glad I was able to help.

JPD
http://www.jpdeni.com/dbman/
Quote Reply
Re: [JPDeni] sorting radio fields contd. In reply to
In Reply To:

You mentioned earlier about "sorting" but not alphabetically -- Book, Translation, Article. There's only one way I can think of to do this -- well, actually two ways. The first way would be to have another field with the sort order. Book would have a "1" in the field, Translation would have a "2" and Article would have a "3." It could pretty easily be done without your having to manually enter the values. The other way would be to stick the numbers at the beginning of the categories -- 1Book, 2Translation, 3Article. Then it would sort the way you want. You could chop off the first character when you print it out so the numbers wouldn't be seen. You could even have the stick the numbers in so you wouldn't have to do it.
I found this thread and this is what I am trying to do on my database (for a list of ranks). I understand the first part adding the number in front. But, the last part..."chopping off the first character when you print it out"...where and how do you do that?

Thanks. Sly

Diana Rae
Quote Reply
Re: [dianarae] sorting radio fields contd. In reply to
I found another string by JPD that relates to the same type of thing as well:

http://www.gossamer-threads.com/...n;guest=148250#55238


" I understand. But the only way you can get it to sort is to "translate" your names into either numbers or other letters that will sort the way you want them to -- so that

ONLINE = 1
ANSWERED = 2
CLOSED = 3

(you could also use "a, b and c" if you wanted)

Then the script can sort by the "translation" instead of the actual word. It can still print out the word, even though the word isn't in your database.

What I want to give you is a way that the script will automatically enter the number when you select the word in either a select field or a radio field.

I suppose it would be possible to work out some other way to do it, but it would be much more complicated. "

------------------
JPD


Again, like the last post, this is what I am trying to do. I have members that have "rank". When search results display for a particular field name I need the results to print out in the proper order (by their rank: Duke, Count, Baron, Knight, Squire).

Which of these (the post here or the post above) and if so could someone figure out the missing parts of either one?

Thanks.



Diana Rae
Quote Reply
Re: [dianarae] sorting radio fields contd. In reply to

kellner
Quote Reply
Re: [kellner] sorting radio fields contd. In reply to
Ya almost said somethin', Kellner? Cool
Diana Rae
Quote Reply
Re: [dianarae] sorting radio fields contd. In reply to
Almost. Turned out too shy in the end Wink

Alas, this code removes an initial number from $rec{'Rank'}:

if ($rec{'Rank'} =~ /^(\d)(\w+)$/) { $rec{'Rank'} = $2;}



Would that answer your questions?

kellner

Last edited by:

kellner: Jan 8, 2002, 2:31 AM
> >