Perl generated navigation menu

J

John Bokma

Gregory said:
However, the more modules you load the slower your cgi runs.
On the web, speed isn't everything, its the ONLY thing.

Early optimizing can be a nice way to shoot yourself in the foot.
 
M

michael

I'm doing a site which will have a navigation menu in the form of an
unordered list, containing groups of URLs and corresponding link names,
which may be defined in simple arrays, eg.:

@flora_and_funa_URLs = ("z0.html","z1.html","z2.html");
@flora_and_funa_Names = ("Flora & Funa", "Pretty Flowers", "Deadly Vines");

@aquatic_creatures_URLs = ("z3.html","z4.html","z5.html");
@aquatic_creatures_Names = ("Aquatic Creatures","Pretty Fish","Don't Eat");

My idea of a perl script would be to generate the menu including some class
variables, and to serve the following functions:

1. Assign a relevant class value to each LI for CSS to provide visual
indication of which section and page is currently on view.

2) Use a suitable for a large site and easy to maintain menu, which can be
generated directly on html pages through SSI for example.

Separate from Perl and HTML; CSS declarations may style a drop menu
whereby nested UL groups would appear on hover of each complete link group
on CSS aware browsers, whilst Lynx type browsers would interpret only
barebone code, eg.:

<ul>
<li><a href="z0.html">Flora & Funa</a>

<ul>
<li><a href="z1.html">Pretty Flowers</a></li>
<li><a href="z2.html">Deadly Vines</a></li>
</ul>

</li>

<li><a href="z3.html">Aquatic Creatures</a>

<ul>
<li><a href="z4.html">Pretty Fish</a></li>
<li><a href="z5.html">Don't Eat</a></li>
</ul>

</li>
</ul>


But all <li>'s would also include either of 3 classes depending on which
URL is accessed:

<li class="in_group"> <-- in which group user access a page
<li class="this_URL"> <-- the current URL on view
<li class="no_match"> <-- if current URL is the group or page

If a user accesses z4.html for example, the html for its current group would
appear as follows:

<li class="in_group"><a href="z3.html">Aquatic Creatures</a>

<ul>
<li class="this_URL"><a href="z4.html">Pretty Fish</a></li>
<li class="in_group"><a href="z5.html">Don't Eat</a></li>
</ul>

</li>

Whilst all LI's of the other group(s) would then have the <li
class="no_match"> assigned.

It is obviously necessary know which URL is accessed, and as URLs may or may
not include www, https etc., it may be easier to reduce URLs to their
filename substrings and compare that with what's in each of the arrays.

Nested <ul> would need to open after the first closing </a> of the first
<li> which in turn would not close until after the last </ul> for each link
group in order to form the nested UL structure.

As a non-perl scripter I have some likely basic questions:

How can a current URL or filename portion be accessed in Perl?

Are there any modules that may be useful in this example, or would it
perhaps be easier to write a script for the purpose?

In which ways could all be easily done?

Any ideas including code snippets (or chunks) would be greatly appreciated,
especially with regards to transforming the above arrays into the
examplified html structure, perhaps by using a for loop?

Many thanks,
Michael
 
T

Tad McClellan

michael said:
I'm doing a site which will have a navigation menu in the form of an
unordered list, containing groups of URLs and corresponding link names,
which may be defined in simple arrays, eg.:

@flora_and_funa_URLs = ("z0.html","z1.html","z2.html");
@flora_and_funa_Names = ("Flora & Funa", "Pretty Flowers", "Deadly Vines");


Related things should be kept together, else it is easy for
them to get out of sync.

So I suggest a "better" data structure would be a LoH:

@flora_and_funa = (
{ url => "z0.html", name => "Flora & Funa" },
{ url => "z1.html", name => "Pretty Flowers" },
{ url => "z2.html", name => "Deadly Vines" },
);
 
M

michael

REQUEST_NAME, SERVER_NAME, SCRIPT_NAME and SCRIPT_FILENAME will tell you

Yes Thanks. It is Apache.
It really is as simple as a loop & print statement. You can go down the
route of using templates if you want.

I guess templates and modules except perhaps CGI would be excessive as the
resulting html code would be fairly short in any case.

Could someone here contruct an example loop & print of the arrays that would
generate the code below it, bearing the nested list syntax in mind?

@flora_and_funa_URLs = ("z0.html","z1.html","z2.html");
@flora_and_funa_Names = ("Flora & Funa", "Pretty Flowers", "Deadly Vines");

@aquatic_creatures_URLs = ("z3.html","z4.html","z5.html");
@aquatic_creatures_Names = ("Aquatic Creatures","Pretty Fish","Don't Eat");

<ul>
<li><a href="z0.html">Flora & Funa</a>

<ul>
<li><a href="z1.html">Pretty Flowers</a></li>
<li><a href="z2.html">Deadly Vines</a></li>
</ul>

</li>

<li><a href="z3.html">Aquatic Creatures</a>

<ul>
<li><a href="z4.html">Pretty Fish</a></li>
<li><a href="z5.html">Don't Eat</a></li>
</ul>

</li>
</ul>

Many thanks,
Michael
 
J

Juha Laiho

Gregory Toomey said:
There are modules like HTML::Template or CGI.pm
http://search.cpan.org/dist/CGI.pm/CGI.pm

However, the more modules you load the slower your cgi runs.
On the web, speed isn't everything, its the ONLY thing.

Hmm.. that much explain the multitude of sites not working properly
(and failing extremely fast...).

Modules tend to create more consistent code, as well as more consistent
HTML. Consistent code may offer possibilities of higher-level
optimisations, whereas consistent HTML renders more predictably in the
various browsers.

So, optimise for speed when speed is the problem. Which does not mean
that one is allowed to write excessively slow code by default.

As for optimising for speed, the largest slowdown with modules tends to
be the module load/initialisation time. This can largely be avoided with
switching from plain CGI to either mod_perl or FastCGI execution
environments -- so, there are other (better) ways to gain speed than
discard use of modules.
 
A

Anno Siegel

michael said:
@flora_and_funa_URLs = ("z0.html","z1.html","z2.html");
@flora_and_funa_Names = ("Flora & Funa", "Pretty Flowers", "Deadly Vines");

"Fauna", not "funa".

Anno
 
P

Peter Wyzl

: >
: > @flora_and_funa_URLs = ("z0.html","z1.html","z2.html");
: > @flora_and_funa_Names = ("Flora & Funa", "Pretty Flowers", "Deadly
Vines");
:
: "Fauna", not "funa".

Thank you...

P
 
T

Tad McClellan

michael said:
Thanks for the tip, first time I've heard of LoH's...


perldoc perlreftut
perldoc perlref
perldoc perllol
perldoc perldsc

the above, including an
@aquatic_creaturs LoH's,


Oh.

I would now suggest a different "better" structure, a HoLoH:

%links = (
flora_and_funa => [
{ url => "z0.html", name => "Flora & Funa" },
{ url => "z1.html", name => "Pretty Flowers" },
{ url => "z2.html", name => "Deadly Vines" },
],
aquatic_creaturs => [
{ url => "z4.html", name => "Pretty Fish" },
{ url => "z5.html", name => "Don't Eat" },
],
);


(those are some odd spellings by the way, that could easily lead
to typos if you happen to actually spell them correctly at some point.
)

If so, please kindly post your code.


Show us the code you've already tried, and we will help you fix it.
 
M

michael

perldoc perlreftut
perldoc perlref
perldoc perllol
perldoc perldsc

Will read....
I would now suggest a different "better" structure, a HoLoH:
Thanks!

Show us the code you've already tried, and we will help you fix it.

Thanks, but I've got no code yet, as I'm trying to figure how to, but your
suggestions should have got me on the right track.

Michael
 
J

Joe Smith

Michael said:
<li class="in_group"><a href="z3.html">Aquatic Creatures</a>
<ul>
<li class="this_URL"><a href="z4.html">Pretty Fish</a></li>
<li class="in_group"><a href="z5.html">Don't Eat</a></li>
</ul>
</li>

That matches #10 in the "Ten Most Violated Homepage Design Guidelines"
in http://www.useit.com/alertbox/20031110.html .

When you are generating z4.html, the middle line should be:

It is obviously necessary know which URL is accessed, ...

No, you are creating files, and you know the name of the file that
you are creating (such as "z4.html"). This is not the case of
accessing a URL, it is the case of creating a file that will
become the target of a URL.
How can a current URL or filename portion be accessed in Perl?

Your question would be appropriate if you were writing a CGI
to process data on the fly. But the rest of your post implies
creating static HTML files offline, then uploading them to a
web server.
Any ideas including code snippets (or chunks) would be greatly appreciated,
especially with regards to transforming the above arrays into the
examplified html structure, perhaps by using a for loop?

It is simple: use a for() loop to generate your html.
Show us what you've tried so far and we can critique it for you.

But if you are saying that you've never used a for() loop before,
this is the wrong place to be posting. Learn the basics first,
ask for help only after you can show putting significant effort
into the task.
-Joe
 
M

michael

<li class="this_URL"><b>Pretty Fish</b></li>

This is of course correct, and in fact what I would ultimately do.
accessing a URL, it is the case of creating a file that will
become the target of a URL.

Sounds right too. I found that $ENV{"DOCUMENT_NAME"} does what I need.
It is simple: use a for() loop to generate your html.

Yes I realise. I'm working on it....

Michael
 
J

Joe Smith

michael said:
Sounds right too. I found that $ENV{"DOCUMENT_NAME"} does what I need.

No, DOCUMENT_NAME is only present in the CGI environment. What you
are writing is not a CGI so $ENV{DOCUMENT_NAME} will not be set.

Do you understand what I'm saying? It is important to know the
difference between programs what create HTML files and CGI scripts.

0. Write a perl script to generate HTML files off-line.
1. Update the data file that the perl script uses.
2. Run the perl script to create a bunch of *.html files.
3. Use FTP or other upload procedure to copy the html files
to the web server.
4. Verify that the changes are visible on the server by using a browser.

Repeat steps 2 through 4 whenever step 1 is performed, which may be
once a week, but definitely not thousands of times per day.

There are valid reasons for using CGI to generate results on the
fly, but the task, as you have stated it, does not require CGI.
-Joe
 
J

Joe Smith

michael said:
As a non-perl scripter I have some likely basic questions:
How can a current URL or filename portion be accessed in Perl?

There is no need to access either when your perl script is creating
both the URLs and the files. The process of creating simple HTML
files does not require the use of a web server and browser.
Are there any modules that may be useful in this example, or would it
perhaps be easier to write a script for the purpose?

Various of the html template modules are suitable.

I know what you are trying to accomplish; I did something like that
ten years ago. I created a script that would take one specific html
file as input data, then use that data to update the "prev", "next",
and and "up" links on all the other html files (and change the
"page N of NNN" text at the bottom of each page).
http://www.inwap.com/mf/reboot/TheEnd.html is the data file.
In which ways could all be easily done?

Any ideas including code snippets (or chunks) would be greatly appreciated,
especially with regards to transforming the above arrays into the
examplified html structure, perhaps by using a for loop?

OK, so you're asking how a for(){} loop could be used for this purpose.

If the items in an array are independent, use

foreach my $element (@array) {
... $element ...
}

But when handling consecutive elements, index into the array.

foreach my $i (0 .. $#array) {
print "Previous = $array[$i-1]\n" unless $i == 0;
print "Current = $array[$i]\n";
print "Next = $array[$i+1]\n" unless $i == $#array;
}

Here is an example of the latter using your data.
-Joe


linux% cat michael.pl
#!/usr/bin/perl
# In reference to Message-ID: <[email protected]>
use strict;
use warnings;

my %links = (
'flora_and_fauna' => [
[ 'z0.html', 'Flora &amp; Fauna' ],
[ 'z1.html', 'Pretty Flowers' ],
[ 'z2.html', 'Deadly Vines' ],
],
'aquatic_creatures' => [
[ 'z3.html', 'Aquatic Creatures' ],
[ 'z4.html', 'Pretty Fish' ],
[ 'z5.html', "Don't Eat" ],
],
);

foreach my $title (sort keys %links) {
print "Creating pages for '$title'\n";
write_group($title, @{$links{$title}});
}

sub write_group {
my ($name,@links) = @_;

foreach my $i1 (0 .. $#links) {
my ($file,$text) = @{$links[$i1]};
open my $htm,'>',$file or warn "Unable to create $file: $!\n" and next;
print " Creating $file for '$text'\n";
print $htm "START OF HTML\n";

foreach my $i2 (0 .. $#links) {
my ($file2,$text2) = @{$links[$i2]};
if ($i2 < $i1) {
print $htm qq(PREV <a href="$file2">$text2</a>\n);
} elsif ($i2 > $i1) {
print $htm qq(NEXT <a href="$file2">$text2</a>\n);
} else {
print $htm qq(THIS is href="$file2" $text2\n);
}
}

print $htm "END OF HTML\n";
close $htm or warn "Possible truncation on $file: $!\n";
}
}

linux% perl michael.pl
Creating pages for 'aquatic_creatures'
Creating z3.html for 'Aquatic Creatures'
Creating z4.html for 'Pretty Fish'
Creating z5.html for 'Don't Eat'
Creating pages for 'flora_and_fauna'
Creating z0.html for 'Flora &amp; Fauna'
Creating z1.html for 'Pretty Flowers'
Creating z2.html for 'Deadly Vines'
linux% head z?.html
==> z0.html <==
START OF HTML
THIS is href="z0.html" Flora &amp; Fauna
NEXT <a href="z1.html">Pretty Flowers</a>
NEXT <a href="z2.html">Deadly Vines</a>
END OF HTML

==> z1.html <==
START OF HTML
PREV <a href="z0.html">Flora &amp; Fauna</a>
THIS is href="z1.html" Pretty Flowers
NEXT <a href="z2.html">Deadly Vines</a>
END OF HTML

==> z2.html <==
START OF HTML
PREV <a href="z0.html">Flora &amp; Fauna</a>
PREV <a href="z1.html">Pretty Flowers</a>
THIS is href="z2.html" Deadly Vines
END OF HTML

==> z3.html <==
START OF HTML
THIS is href="z3.html" Aquatic Creatures
NEXT <a href="z4.html">Pretty Fish</a>
NEXT <a href="z5.html">Don't Eat</a>
END OF HTML

==> z4.html <==
START OF HTML
PREV <a href="z3.html">Aquatic Creatures</a>
THIS is href="z4.html" Pretty Fish
NEXT <a href="z5.html">Don't Eat</a>
END OF HTML

==> z5.html <==
START OF HTML
PREV <a href="z3.html">Aquatic Creatures</a>
PREV <a href="z4.html">Pretty Fish</a>
THIS is href="z5.html" Don't Eat
END OF HTML
linux%
 
E

Erik Aronesty

There are modules like HTML::Template or CGI.pm
Hmm.. that much explain the multitude of sites not working properly
(and failing extremely fast...).

Modules tend to create more consistent code, as well as more consistent
HTML. Consistent code may offer possibilities of higher-level
optimisations, whereas consistent HTML renders more predictably in the
various browsers.

So, optimise for speed when speed is the problem. Which does not mean
that one is allowed to write excessively slow code by default.

As for optimising for speed, the largest slowdown with modules tends to
be the module load/initialisation time. This can largely be avoided with
switching from plain CGI to either mod_perl or FastCGI execution
environments -- so, there are other (better) ways to gain speed than
discard use of modules.

I wrote a nonforking pure perl webserver yesterday to deal with Apache
speed issues:

http://www.documentroot.com/code/ppcgid

For my application it was three to 10 times faster than Apache, and had
a more graceful degradation curve and user experience when overloaded.

Apache was hanging, crashing and consuming enormous amounts of RAM. My
hacky webserver dealt with the same load (a couple hundred hits per
second) on the same hardware (an 800mhz celeron) with about 60% CPU.

So, it's exactly the opposite of your suggestion. It's a hack that
works, but only for a very specific kinds of application. It's also a
bit more DDOS resistent (for certain kinds of basic DDOS'es) because of
the dual timeouts.

"Generality" and efficiency are often opposites in code.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,780
Messages
2,569,611
Members
45,276
Latest member
Sawatmakal

Latest Threads

Top