• Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 998
  • Last Modified:

@DocNumber in a category

I've struck another wall....
I'm using R6 to create a website with navigation as offered on www.burmees.nl/menu (vertical with frames). I want the "menu"-lines ("....menu1...", "...menu1_1...", "...menu1_2...") generated from a view, so I can easily hide a button if the database is restricted.
I need multiple sets of menus to control at least two languages, of perhaps later multiple sites.
I thought of using a single category enbedded view to do this. @DocChildren will count the no. op sub-entries and @DocNumber("_") takes care of the menu numbering.
Problem is the single category: a category would add an additional level in the count and I NEED to start off on "menu1".
If I don't use the category, the counting is ok but I'd have to use a @DbLookup.... fine with me if it would deliver response documents as well.
Leaving the responses out as well, the whole counting system collapses!
Any good ideas?
I wish I could perform a @ReplaceSubstring on @DocNumber's result....
0
CRAK
Asked:
CRAK
  • 6
  • 3
  • 2
  • +1
2 Solutions
 
Bozzie4Commented:
Use 2 views ?
0
 
CRAKAuthor Commented:
Can you be more specific?

I thought of another way that might work (haven't tried it yet): use javascript to modify the retrieved lines and "document.write" the results.
0
 
HappyFunBallCommented:
It's not ideal, but you could replace the @DocNumber column with your own "DocNumber" field, then use an agent to populate that field.  The agent could be set to run when any of the documents change, just in case that changes the menu for you.  Basically, you'd just need to loop through the view using a ViewNavigator and set the field based on the GetPos method.
0
Concerto Cloud for Software Providers & ISVs

Can Concerto Cloud Services help you focus on evolving your application offerings, while delivering the best cloud experience to your customers? From DevOps to revenue models and customer support, the answer is yes!

Learn how Concerto can help you.

 
Bozzie4Commented:
I mean, use 1 view that's simply sorted, and that you can use to retrieve your starting point, and use the second view with the @docnumbers to do the rest of the lookups.

But although using @docnumber sounds interesting, it really isn't.  It only comes in handy when using it on the browser (javascript can parse it, because it's text in the browser).
It's probably easier to just make a lookup routine - not based on number in the view, but on position in a tree :

Use a 'key' to sort :
First document:
startmenu

Submenu's for startmenu:
startmenu#menu1
startmenu#menu2
startmenu#menu3

sub-sub menu's :
startmenu#menu1#subsub1

I use this also in a multilanguage application, where the first element in a key is the language :

EN
EN#First Item
EN#Second Item

....

So a @dblookup for all EN items is possible using the PartialResult parameter in R6.  Parsing would be quite easy, in formula or in javascript.

cheers,

Tom
0
 
CRAKAuthor Commented:
I thought of that, but it's not what I try top archieve:
Imagine that I have a menu definition like:
  menu1 = ....
  menu1_1 = ....
  menu1_2 = ....
  menu1_3 = ....
  menu2 = ....

Now one of the users is not permitted to access menu1_2.
In his menu, "our" menu1_3 should shift up and be shown as the new menu1_2.

@DocNumber does recalc in this case I hope.... (i.e. it doesn't skip menu1_2)...? I haven't tried yet as I am developping on a client only.
0
 
CRAKAuthor Commented:
That was a comment to HappyFunBall....
0
 
HappyFunBallCommented:
I like Bozzie4's idea.  It is very flexible and much easier to code.

The only alternative I can come up with right now is outputting all the menu code via an agent rather than a view.  The agent would use Print statements to dynamically output the same code the view does.  This way you can control everything that gets output.  

Talk about reinventing the wheel...
0
 
Bozzie4Commented:
Yes, an agent is very good to combine with the way to sort data.

<script language src="/db.nsf/agent?openagent"></script>

Your agent can use print statement , and to output javascript code, do it like this pseudocode


Print "ContentType: text/javascript"
do while not doc is nothing
Print "menu=" + doc.url
set doc = view.getnextdocument(doc)
loop
0
 
CRAKAuthor Commented:
Both could work, but I think I have just mastered a 3rd, more exotic way.....

I start off in the categorized view that delivers the additional level (Menu1_1 instead of Menu1).
I set that view to show HTML and modify it to trigger a js conversion function.
Col 1 = Menu name (categorized)
Col 2 = Menu entry sorting (sorted)
Col 3 = "convertMenuEntry('Menu" + @DocNumber("_") + "= new Array(" + <required parameters part 1> + @Text(@DocChildren) + <required parameters part 2> + ");');" + @NewLine

It's a bit of fuss as some parameters may contain links like "javascript: alert('unavailable')". I need to mark quotes (single/double) with backslashes, or JS won't be able to handle them correctly.

I have created two of these views: one for dutch menus, another for english ones (and a third as UI view).
The views are embedded by computation on a form. Both the language and the manu name are provided as URL parameters. Viewheaders are hidden.

Around the embedded view I have added some more JS:

[<Script language="javascript">
function convertMenuEntry(txt)
{
document.writeln('<scr' + 'ipt>' + 'Menu' + txt.substring(txt.indexOf('_')+1, txt.length) + '</scr' + 'ipt>');
}
<This is where the view goes>
alert('Result:\n' + Menu1);
</Script>]

At this stage the contents of the Menu1-array is shown in an alert-box.

Note that " '<scr' + 'ipt>' " and " '</scr' + 'ipt>' " look weird, but are quite important.
I found it on EE:.... plain " '<script>' " and " '</script>' " won't get you there!

It required no agents, additional refreshes of documents, no lookups etc. Yet it's fast, automatic and on the fly!

It's been another great day!  ;-))


Splitting point for your (also feasible) solutions....
Thanks for your thoughts!
0
 
CRAKAuthor Commented:
For anyone visiting this "PAQ":
It looked promising at first, by the solution I described will cause a lot of problems.
As I reread designer help on @DocNumber, I found one line that said it all:
"You cannot use this function in Web applications."

I don't understand why I saw it work at first, including hiding entries for certain userroles, but it's easy to hit error in a few trials! Don't go for it!
0
 
madheeswarCommented:
Help tells @MailSend won't work.

Some times it works for users.

And @iSDocbeingSaved won't work on web.  But it is not documented.

Thanks for pointing CRAK.
0
 
CRAKAuthor Commented:
Since I have always enjoyed odd solutions, I'll post my current solution.
Remember that my server is only a tiny little thing... JS is helping me out shifting pressure from the server to clients...

I am using 3 views:
One showing the menu structures in both languages (for editing)
Two (a dutch and an english one) to feed en embedded view with menu data.

These latter two are categorized (for menu selection through single category views), a hidden column to force sorting, another to count the number of top-level documents (1 for doc, 0 for response), and a last column...
This last one is JS code. In pseudo code:
appendToMenuArray(<doc id>, $ref, <menu fields>)

<menu fields> contains colors, button labels etc. And @DocChildren (glad that one works perfectly!)

appendToMenuEntry is defined (along with the embedded view) on a subform, after I defined an arrray:
var cAr = -1;
var ar = new Array();

function appendToMenuArray(p1, p2, p3)
{
   cAr++;
   ar.length=cAr;
   ar[cAr]=new Array(p1,p2,p3);
}

Instead of an independant set of arrays, all data is now stored in a array(0-n).


Below the embedded view, I launch another JS function:
buildMenuConstructor();

defined as:
function buildMenuConstructor()
{
   var cPar=0;
   for (var m=0; m<ar.length; m++)
   {
      if (ar[m][1]=='')
      {
         vPar=ar[m][0];
         cPar++;
         ar[m][0]='';
         ar[m][1]=cPar;
      }
      else
      {
         vPar=ar[m][0];
         ar[m][0]='';
      }
      var cSub = 0;
      for (var n=(m+1); n<ar.length; n++)
      {
         if (ar[n][1]==vPar)
         {
            cSub++;
            ar[n][1]=ar[m][1]+'_'+cSub;
         }
      }
   }

   for (var m=0; m<ar.length; m++)
   {
      document.writeln('<scr' + 'ipt>Menu' + ar[m][1] + ' = new Array(' + ar[m][2] + ')</scr' + 'ipt>\n');
   }
}

Based on the contents of the doc id and $ref, the Menu-vars (numbers) are defined.... as dynamically defined JS! (ever seen JS writing new JS before?)

Last hard-coded fragment is:
document.writeln('START<BR><script type=\'text/javascript\' src=\'<computed value>\'></script>');
<computed value> provides the url of menu13_com.js, the menu's JS engine.
Using the writeln, I make sure this code is only launched AFTER Menu1 and simular dynamically defined vars were defined.

Hiding a button might result in the definition of a JS var like Menu<doc id>, but that won't harm the menu's JS engine: it'll only look for sequential ranges of menu vars.

I've only done a few tests, based on a single userrole. Nothing hard yet, but it appears to work smoothly!

Enjoy!
0

Featured Post

Industry Leaders: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

  • 6
  • 3
  • 2
  • +1
Tackle projects and never again get stuck behind a technical roadblock.
Join Now