Schrift
[thread]3056[/thread]

Dynamische Navigation mit HTML::Template

Leser: 2


<< |< 1 2 3 >| >> 23 Einträge, 3 Seiten
tonewheel
 2007-05-01 13:11
#28965 #28965
User since
2006-10-01
182 Artikel
BenutzerIn
[default_avatar]
Hallo,

Eine Suche nach "navigation" hat meine Fragen nicht beantwortet, daher frage ich mal nach. Kann man mittels HTML::Template Seiten erstellen, die eine dynamische Navigation auf 2 Ebenen beinhalten? Bisher habe ich mit HTML::Template nur etwas herum probiert, das Thema ist recht neu für mich, finde es aber geeignet dafür. Mir geht es nicht um Syntax, sondern nur um die Logik. Wer ruft wann, was auf - brauche ich mehrere Templates - wo liegt der Content - ist der Ansatz überhaut sinnvoll - ggf. Kombination mit YAML

Danke für Antworten.

Grüße
renee
 2007-05-01 13:49
#28966 #28966
User since
2003-08-04
14371 Artikel
ModeratorIn
[Homepage] [default_avatar]
Was verstehst Du unter "dynamische Navigation"?

Mit CPAN:HTML::Template::Compiled kannst Du TMPL_INCLUDE_VAR verwenden.

Beispiel:

Template.tmpl:
Code: (dl )
<html><body><TMPL_INCLUDE_VAR NAME=DYNAMIC_NAVI></body></html>


Navi1.tmpl:
Code: (dl )
1
2
3
4
<ul>
<li>Navi1</li>
<li>Navi1.1</li>
</ul>


Navi2.tmpl:
Code: (dl )
1
2
3
4
<ul>
<li>Navi2</li>
<li>Navi2.1</li>
</ul>


Skript:
Code (perl): (dl )
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#!/usr/bin/perl

use strict;
use warnings;
use CGI;
use HTML::Template::Compiled;

my $file = './Template.tmpl';
my @navis = qw( navi1.tmpl navi2.tmpl);
my $index = (int(rand 2) % 2);

my $tmpl = HTML::Template::Compiled->new(filename => $file);
$tmpl->param(DYNAMIC_NAVI => $navis[$index]);

print CGI::header,$tmpl->output;
OTRS-Erweiterungen (http://feature-addons.de/)
Frankfurt Perlmongers (http://frankfurt.pm/)
--

Unterlagen OTRS-Workshop 2012: http://otrs.perl-services.de/workshop.html
Perl-Entwicklung: http://perl-services.de/
Ronnie
 2007-05-01 14:25
#28967 #28967
User since
2003-08-14
2022 Artikel
BenutzerIn
[default_avatar]
Ich empfehle auch CPAN:HTML::Template::Compiled. Ansonsten könnte ich mir einen entsprechenden Ansatz ungefähr so vorstellen:
Code: (dl )
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
#!/usr/bin/perl

use strict;
use warnings;

package HTML::Widget::NavEntry;
use Moose;

has 'title' => ( is => 'rw' );
has 'link' => ( is => 'rw' );

sub to_html {
my $self = shift;
return "\t" . '<a href="' . $self->link . '">' . $self->title . '</a>' . "\n";
}

package HTML::Widget::SubNavigation;
use Moose;

has 'title' => ( is => 'rw', required => 1 );
has 'entries' => (
isa => 'ArrayRef',
is => 'rw',
default => sub { return [] }
);

sub to_html {
my $self = shift;
my $o = '<div id="nav_' . $self->title . '">' . "\n";
$o .= $_->to_html for @{$self->entries};
$o .= '</div>' . "\n";
return $o;
}

sub add_entry {
my $self = shift;
my $entry = shift;
return unless blessed $entry eq 'HTML::Widget::NavEntry';
push @{$self->entries}, $entry;
}

package HTML::Widget::Navigation;
use Moose;

has 'entries' => (
isa => 'ArrayRef',
is => 'rw',
default => sub { return [] }
);

sub to_html {
my $self = shift;
my $o = '<div id="navigation">' . "\n";
$o .= $_->to_html for @{$self->entries};
$o .= '</div>' . "\n" x 2;
return $o;
}

sub selected_to_html {
my $self = shift;
my $selection = shift;

my $o = '<div id="navigation">' . "\n";
$o .= $_->to_html for (grep { $_->title eq $selection } @{$self->entries});
$o .= '</div>' . "\n" x 2;
return $o;
}

sub add_entry {
my $self = shift;
my $entry = shift;
return unless (
blessed $entry eq 'HTML::Widget::NavEntry'
or blessed $entry eq 'HTML::Widget::SubNavigation'
);
push @{$self->entries}, $entry;
}

package main;

my $s_nav1 = HTML::Widget::SubNavigation->new( title => 'foo' );

$s_nav1->add_entry(
HTML::Widget::NavEntry->new( title => 'foo', link => 'foo.pl' )
);

$s_nav1->add_entry(
HTML::Widget::NavEntry->new(
title => 'bar',
link => 'foo.pl?content=bar'
)
);

$s_nav1->add_entry(
HTML::Widget::NavEntry->new( title => 'buz', link => 'buz.pl' )
);

my $s_nav2 = HTML::Widget::SubNavigation->new( title => 'yankee' );

$s_nav2->add_entry(
HTML::Widget::NavEntry->new( title => 'yankee', link => 'yankee.pl' )
);

$s_nav2->add_entry(
HTML::Widget::NavEntry->new( title => 'zulu', link => 'zulu.pl' )
);

my $nav = HTML::Widget::Navigation->new;
$nav->add_entry( $s_nav1 );
$nav->add_entry( $s_nav2 );

print $nav->to_html;
print $nav->selected_to_html('foo');

Du müsstest nur einen Weg finden dem Formular jedesmal die Info mitzugeben welche SubNavigation du angezeigt haben willst.

Die Ausgabe sieht beispielhaft so aus:
Code: (dl )
1
2
3
4
5
6
7
8
9
10
11
<div id="navigation">
<div id="nav_foo">
<a href="foo.pl">foo</a>
<a href="foo.pl?content=bar">bar</a>
<a href="buz.pl">buz</a>
</div>
<div id="nav_yankee">
<a href="yankee.pl">yankee</a>
<a href="zulu.pl">zulu</a>
</div>
</div>

bzw. mit Auswahl auf 'foo':
Code: (dl )
1
2
3
4
5
6
7
<div id="navigation">
<div id="nav_foo">
<a href="foo.pl">foo</a>
<a href="foo.pl?content=bar">bar</a>
<a href="buz.pl">buz</a>
</div>
</div>

EDIT: Evtl. könnte man sowas nett mit CPAN:CGI::Ajax kombinieren?!\n\n

<!--EDIT|Ronnie|1178015217-->
Ronnie
 2007-05-01 14:48
#28968 #28968
User since
2003-08-14
2022 Artikel
BenutzerIn
[default_avatar]
Hmm, YAML kann man natürlich einbinden, aber bei komplexeren Dingen riskiert man immer sich irgendwo in den Fuss zu schiessen. Mit YAML sähe dann so aus:
Code: (dl )
1
2
3
4
5
use YAML qw/Dump LoadFile/;
my $nav = LoadFile('nav.yaml');

print $nav->to_html;
print $nav->selected_to_html('foo');

wobei nav.yaml so aussieht:
Code: (dl )
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
--- !!perl/hash:HTML::Widget::Navigation
entries:
- !!perl/hash:HTML::Widget::SubNavigation
entries:
- !!perl/hash:HTML::Widget::NavEntry
link: foo.pl
title: foo
- !!perl/hash:HTML::Widget::NavEntry
link: foo.pl?content=bar
title: bar
- !!perl/hash:HTML::Widget::NavEntry
link: buz.pl
title: buz
title: foo
- !!perl/hash:HTML::Widget::SubNavigation
entries:
- !!perl/hash:HTML::Widget::NavEntry
link: yankee.pl
title: yankee
- !!perl/hash:HTML::Widget::NavEntry
link: zulu.pl
title: zulu
title: yankee

Das könnte man sicher noch etwas eleganter gestalten.
tonewheel
 2007-05-01 15:27
#28969 #28969
User since
2006-10-01
182 Artikel
BenutzerIn
[default_avatar]
@renee, @ronnie: Danke für die Antworten. In die Richtung geht es, aber mein eigentliches Problem ist mehr das Zusammenspiel aller Komponenten. Vielleicht etwas formaler; Dass es um Navigations und Subnavigationselemente geht, ist klar. Sowas könnte man ja auch mit einzelnen, statisch erzeugten Webseiten und einem mords Aufwand machen. Sobald dann neue Seiten hinzu kommen, müssten die neuen Links wieder auf die alten Seiten mit drauf, damit man von/nach überall problemlos navigieren kann (der Aufwand würde dann immer größer). Mein Problem ist mehr dahingehend, dass es mir etwas an Vorstellungskraft fehlt, ob so ein Vorhaben mit einem oder mehreren Skripten zu realisieren ist. Weiterhin ist auch nicht klar, ob dazu ein Template (bei Benutzung von HTML::Template) ausreicht, und auch nicht, wo letztlich der Content liegt (wohl mehr in Textdateien oder Datenbank). Und letztlich auch die Parameterübergabe.
@ronnie: wir meinen nicht das gleiche YAML. Siehe Link.

Grüße
Ronnie
 2007-05-01 20:22
#28970 #28970
User since
2003-08-14
2022 Artikel
BenutzerIn
[default_avatar]
Hier nochmal ein komplettes Beispiel mit CPAN:CGI::Ajax:
Code: (dl )
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
#!/usr/bin/perl

use strict;
use warnings;

use CGI;
use CGI::Carp qw/warningsToBrowser fatalsToBrowser/;
use CGI::Ajax;

use HTML::Template::Compiled;

package HTML::Widget::NavEntry;
use Moose;

has 'title' => ( is => 'rw' );
has 'link' => ( is => 'rw' );

sub to_html {
my $self = shift;
return "\t" . '<a href="' . $self->link . '">' . $self->title . '</a>' . "\n";
}

package HTML::Widget::SubNavigation;
use Moose;

has 'title' => ( is => 'rw', required => 1 );
has 'entries' => (
isa => 'ArrayRef',
is => 'rw',
default => sub { return [] }
);

sub to_html {
my $self = shift;
my $o = '<div class="subnav" id="nav_' . $self->title . '">' . "\n";
$o .= '<span class="sub_level">' . $self->title . '</span>' . "\n";
$o .= $_->to_html for @{$self->entries};
$o .= '</div>' . "\n";
return $o;
}

sub add_entry {
my $self = shift;
my $entry = shift;
return unless blessed $entry eq 'HTML::Widget::NavEntry';
push @{$self->entries}, $entry;
}

package HTML::Widget::Navigation;
use Moose;

has 'entries' => (
isa => 'ArrayRef',
is => 'rw',
default => sub { return [] }
);

sub to_html {
my $self = shift;
my $o = '<div id="navigation">' . "\n";
$o .= $_->to_html for @{$self->entries};
$o .= '</div>' . "\n" x 2;
return $o;
}

sub selected_to_html {
my $self = shift;
my $selection = shift;

my $o = '<div id="navigation">' . "\n";
$o .= $_->to_html for (grep { $_->title =~ /$selection/ } @{$self->entries});
$o .= '</div>' . "\n" x 2;
return $o;
}

sub add_entry {
my $self = shift;
my $entry = shift;
return unless (
blessed $entry eq 'HTML::Widget::NavEntry'
or blessed $entry eq 'HTML::Widget::SubNavigation'
);
push @{$self->entries}, $entry;
}

package main;

my $s_nav1 = HTML::Widget::SubNavigation->new( title => 'foo' );

$s_nav1->add_entry(
HTML::Widget::NavEntry->new( title => 'foo', link => 'foo.pl' )
);

$s_nav1->add_entry(
HTML::Widget::NavEntry->new(
title => 'bar',
link => 'foo.pl?content=bar'
)
);

$s_nav1->add_entry(
HTML::Widget::NavEntry->new( title => 'buz', link => 'buz.pl' )
);

my $s_nav2 = HTML::Widget::SubNavigation->new( title => 'ooperl' );

$s_nav2->add_entry(
HTML::Widget::NavEntry->new( title => 'yankee', link => 'yankee.pl' )
);

$s_nav2->add_entry(
HTML::Widget::NavEntry->new( title => 'zulu', link => 'zulu.pl' )
);

my $nav = HTML::Widget::Navigation->new;
$nav->add_entry( $s_nav1 );
$nav->add_entry( $s_nav2 );

my $q = CGI->new;
my $selection = $q->param('sel_nav');

my $pjx = new CGI::Ajax( 'filter' => sub {
my $selection = shift || '';
return $nav->selected_to_html($selection);
} );

my $tmpl = HTML::Template::Compiled->new(filename => 'nav.tmpl');

$tmpl->param(
nav => $selection ? $nav->selected_to_html($selection) : $nav->to_html
);

print $pjx->build_html($q,$tmpl->output);

Template:
Code: (dl )
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
<!DOCTYPE html
PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" lang="en-US" xml:lang="en-US">
<head>
<title>foobar</title>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
<style type="text/css" media="screen">
/* <![CDATA[ */

body { font-family: Arial, Helvetica; }

#navigation {
background-color: #fca;
}

.subnav {
margin: 2px;
padding: 8px;
color: #f00;
border-style: solid;
border-width: 0px;
border-bottom-width: 1px;
border-color: �
}
/* ]]> */
</style>

</head>
<body>
<h3>Navigation</h3>
<%= nav %>
<hr />
<form>
<input type="text" name="sel_nav" id="sel_nav" onkeyup="filter( ['sel_nav'], ['navigation'] );" />
<input type="submit" name=".submit" />
</form>
</body>
</html>

So sieht es aus:
http://www.ronnie-neumann.de/trashbin/ajax.png
Ronnie
 2007-05-01 20:24
#28971 #28971
User since
2003-08-14
2022 Artikel
BenutzerIn
[default_avatar]
@tonewheel: Erstaunlich was alles YAML ist ;)

Irgendwie ist mir deine Problemstellung nicht vollständig klar. Letzten Endes hängt die Art und Weise wie du deine Navigation erstellst doch davon ab wie deine Seiten erzeugt werden. WebApp mit Datenbank, oder CMS, oder teilweise statische Seiten. Der Rest ist nur Aufbereitung zur Präsentation, oder?!
tonewheel
 2007-05-01 20:57
#28972 #28972
User since
2006-10-01
182 Artikel
BenutzerIn
[default_avatar]
[quote=Ronnie,01.05.2007, 18:24]@tonewheel: Erstaunlich was alles YAML ist ;)
[/quote]
;)

[quote=Ronnie,01.05.2007, 18:24]
Irgendwie ist mir deine Problemstellung nicht vollständig klar. Letzten Endes hängt die Art und Weise wie du deine Navigation erstellst doch davon ab wie deine Seiten erzeugt werden. WebApp mit Datenbank, oder CMS, oder teilweise statische Seiten. Der Rest ist nur Aufbereitung zur Präsentation, oder?![/quote]

Gut ausdrücken war noch nie meine Stärke. Ich benutze keinerlei CMS, o.ä. Es geht um ein paar Seiten, die ich von Hand erstellen will. Daher der Gedanke an das Template, um Inhalt und Design zu trennen. Ich versuche es, anders asutudrücken;
Angenommen, zum Aufrufen der ersten Seite wird ein Skript verwendet. Dieses lädt das Template und ggf. den Content aus einer Textdatei oder Datenbank. Ebenso wird die Navigation erzeugt. Wenn ich nun einen Link anwähle, was passiert dann? Kann ich das gleiche Skript, das die Seite erzeugt hat, wieder aufrufen und diesem mitgeben, dass nun ein anderer Content zu laden und das Navigationsmenue entsprechend umzustellen ist?
Oder; es wird die erste Ebene im Tree der Navigation ausgeählt, der Content bleibt bestehen, aber die Navigation muss die entsprechenden Links unterhalb des ausgewählten Knotens anzeigen und die bisherigen verstecken. Auch hier ist wieder die Frage, ob das Skript erneut aufgerufen werden muss. Soweit ich weiss, bleibt das Skript doch nicht im Cache, muss also immer wieder neu geladen werden?!
Zusatz: Aehm, danke für Dein Beispiel mit Ajax. Zeigt bei mir allerdings das Verhalten, dass alles verschwindet, wenn auch nur ein Zeichen eingegeben wird. Liegt wohl am Browser.\n\n

<!--EDIT|tonewheel|1178038766-->
bloonix
 2007-05-01 21:06
#28973 #28973
User since
2005-12-17
1615 Artikel
HausmeisterIn
[Homepage]
user image
Hier der Link zum Anschauen

Code: (dl )
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
use strict;
use warnings;
use Template;
use CGI;

my $cgi  = new CGI;
my $navi = $cgi->param('navi') || 'else';

my $template = Template->new;
print "Content-Type: text/html\n\n";
$template->process(\*DATA, { navi => $navi, navis => [ 'main', 'foo', 'else' ] });

__END__
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
  <title>[% title %]</title>
  <meta http-equiv="content-type" content="text/html; charset=UTF-8">
</head>
<body>
<form action="navi.cgi" method="POST">
<select name="navi" size="1">
[% FOREACH value = navis %]
  <option value="[% value %]" [% IF value == navi %] selected [% END %]>[% value %]</option>
[% END %]
</select>
<button type="submit">Submit</button>
</form>
<ul>
[% IF navi == 'main'%]
  <li>main foo</li>
  <li>main bar</li>
  <li>main baz</li>
[% ELSIF navi ==  'foo' %]
  <li>foo foo</li>
  <li>foo bar</li>
  <li>foo baz</li>
[% ELSE %]
  <li>else foo</li>
  <li>else bar</li>
  <li>else baz</li>
[% END %]
</ul>
</body>
</html>
\n\n

<!--EDIT|opi|1178039714-->
What is a good module? That's hard to say.
What is good code? That's also hard to say.
One man's Thing of Beauty is another's man's Evil Hack.
Ronnie
 2007-05-01 21:11
#28974 #28974
User since
2003-08-14
2022 Artikel
BenutzerIn
[default_avatar]
Quote
Wenn ich nun einen Link anwähle, was passiert dann? Kann ich das gleiche Skript, das die Seite erzeugt hat, wieder aufrufen und diesem mitgeben, dass nun ein anderer Content zu laden und das Navigationsmenue entsprechend umzustellen ist?

Ja, das ist gut machbar. Du musst nur eine Information mit transportieren wo du dich befindest. Evtl. per hidden-tag o.ä.
Quote
Zusatz: Aehm, danke für Dein Beispiel mit Ajax. Zeigt bei mir allerdings das Verhalten, dass alles verschwindet, wenn auch nur ein Zeichen eingegeben wird. Liegt wohl am Browser.

Evtl. mal statt onkeyup onchange oder onblur probieren.
<< |< 1 2 3 >| >> 23 Einträge, 3 Seiten



View all threads created 2007-05-01 13:11.