Reputation: 1
<header>
<script type="text/javascript">
function hideit()
{
var x1 = document.getElementsByTagName("ol").item(0);
var x = document.getElementsByTagName("ol");
for (var i = 0; i < x.length; i++)
x[i].style.display="none";
}
function showit()
{
var x1 = document.getElementsByTagName("ol").item(0);
var x=document.getElementsByTagName("ol");
for (var i = 0; i < x.length; i++)
x[i].style.display="";
}
</script><header>
<body>
foreach $key (keys %{$stats_data{$out}}) {
print $indexfd ("<input onclick=\"showit()\" type=\"button\" id=\"<?perl echo $key; ?>\" value=\"showit\"><br><input onclick=\"hideit()\" type=\"button\" id=\"<?perl echo $key; ?>\" value=\"hideit\"><br><b><ol id=$key>$stats_data{$out}{$key}<ol id=$key> </b><br>");
}</body>
I am creating an html document with perl. I wrote an event mouseover and mouseout to happen for every perl variable (over a loop). But looks like the event controls all the variables at the same time. How do I write the event only once but enable it to individually be applied for each item: this is what I have currently
but this html when displayed, does not let me control the event separately for each $key
.
Even though the buttons do get created for each $key, clicking on one, controls the $stats_data{$out}{$key}
of all.
I even tried passing the id to the show/hide script, but no luck.
Upvotes: 0
Views: 1609
Reputation: 54323
Your code looks like you are trying to mix Perl with HTML in a way you would use PHP. This does not work in Perl.
I tried fixing your Perl code first. This will print to your filehandle (which I omitted), but will not not give you the working JavaScript code. I did not change that since I did not understand what you want to do. More on that later.
use strict;
use warnings;
# open of $indexfd filehandle goes here..
# print head of HTML page
print $indexfd <<HTML
<html>
<header>
<script type="text/javascript">
function hideit() {
var x1 = document.getElementsByTagName("ol").item(0);
var x = document.getElementsByTagName("ol");
for (var i = 0; i < x.length; i++)
x[i].style.display="none";
}
function showit() {
var x1 = document.getElementsByTagName("ol").item(0);
var x=document.getElementsByTagName("ol");
for (var i = 0; i < x.length; i++)
x[i].style.display="";
}
</script>
</header>
<body>
HTML
;
# If I see this correctly, %stats_data looks like this:
my %stats_data = (
'out1' => {
'key1' => 'val1',
'key2' => 'val2',
},
'out2' => {
'key1' => 'val1',
'key2' => 'val2',
},
);
my $out = 'out1'; # you need the $out from somewhere
# print buttons for each data thingy - you'll want to sort them probably
foreach my $key (sort keys %{$stats_data{$out}}) {
print $indexfd
qq~<input onclick="showit()" type="button" id="$key" value="showit"><br />~,
qq~<input onclick="hideit()" type="button" id="$key" value="hideit"><br/>~,
# Because $stats_data{$out} is a hash ref you need the -> operator here
qq~<ol id="$key"><li><b>$stats_data{$out}->{$key}</b></li></ol><br/>~;
}
print $indexfd qq~<p>more html...</p></body></html>~;
So there are a few things worth mentioning.
print $indexfd ("<input onclick=\"showit()\" type=\"button\" id=\"<?perl echo $key; ?>\" value=\"showit\"><br><input onclick=\"hideit()\" type=\"button\" id=\"<?perl echo $key; ?>\" value=\"hideit\"><br><b><ol id=$key>$stats_data{$out}{$key}<ol id=$key> </b><br>");
In this rather long line of code you used <?perl echo $key; ?>
which looks like php and doesn't work. You also used <ol id=$key>
which works because you used double-quotes "..."
. Perl substitutes the variables inside the "-delimited string for their values. You don't need that php-like stuff. In order to save yourself the effort of escaping all the double quotes in the HTML code you can use the qq
-Operator. See perlop for more infos.
I explained about the %stats_data
data structure in my comments.
For printing the large chunk of HTML, I used HERE docs.
Let's talk about your JavaScript now.
Even though the buttons do get created for each
$key
, clicking on one, controls the$stats_data{$out}{$key}
of all.
This is because of the way you designed your hideit()
and showit()
functions. I'm not really ceratin what you want to achieve. If you look at my %stats_data
you'll see that there are several keys in 'out1'. That lets the foreach-loop print a set of buttons for each of those keys. The buttons both have the same key as their id, as does the ol. That is not correct. An id-attribute has to be unique.
Furthermore, there were some basic issues in your html which I took the liberty to fix as well. If you open an <ol id="foo">
container, you need to close it like </ol>
. Since <ol>
is a block-level element, you shouldn't put the inline element <b>
outside it, but rather inside the ol's <li>
elements (which I omitted). It would be better yet to just assign css ``style="font-weight: bold" to the li items or better yet give them classes.
I'll take one last guess at what you were trying to do with the JavaScript. If you have several paragraphs of text and you want to hide them with buttons, you could do that like my untested code here.
Javascript:
function toggle(id) {
if (document.getElementById(id).style.display == 'block' ) {
document.getElementById(id).style.display = 'none';
} else {
document.getElementById(id).style.display = 'block';
}
}
HTML:
<div>
<input type="button" name="toggle1" id="toggle1" onclick="toggle('p1')" />
<p id="p1">Lorem ipsum dolor set ... foo a lot of text 1.</p>
<input type="button" name="toggle2" id="toggle2" onclick="toggle('p2')" />
<p id="p2">Lorem ipsum dolor set ... foo a lot of text 2.</p>
</div>
In this case, the function checks whether the paragraph is shown or not. The display-value needs to be set to 'none' or 'block', because the p-element is a block-level element.
Please try to post more specific information about the data you use with your script if you need any more help.
EDIT: In the following code I changed the JS functions to both take an id (the key) as a parameter. They only show or hide the lists associated with this key. I changed the button's ids so they're not the same. I also added a div around each pair of buttons and list to make it clearer what belongs where.
use strict;
use warnings;
# open of $indexfd filehandle goes here..
my $indexfd;
# print head of HTML page
print $indexfd <<HTML
<html>
<header>
<script type="text/javascript">
function hideit(key) {
document.getElementById(key).style.display = "none";
}
function showit(key) {
document.getElementById(key).style.display = "";
}
</script>
</header>
<body>
HTML
;
# If I see this correctly, %stats_data looks like this:
my %stats_data = (
'out1' => {
'key1' => 'val1',
'key2' => 'val2',
},
'out2' => {
'key1' => 'val1',
'key2' => 'val2',
},
);
my $out = 'out1'; # you need the $out from somewhere
foreach my $key (sort keys %{$stats_data{$out}}) {
print $indexfd
qq~<div id="div_$key">\n~, # Add a div around the $key-elements
qq~<input onclick="showit('$key')" type="button" id="btn_show_$key" value="showit">\n~,
qq~<input onclick="hideit('$key')" type="button" id="btn_show_$key" value="hideit"><br/>\n~,
qq~<ol id="$key"><li><b>$stats_data{$out}->{$key}</b></li></ol>\n~,
qq~</div>\n~;
}
print $indexfd qq~<p>more html...</p></body></html>~;
Upvotes: 7
Reputation: 132802
It looks like you want one of Perl's templating modules, such as Template Toolkit. It allows you to embed Perl snippets inside larger documents then process them such that the Perl parts fill in whatever you need.
Here's an example from one of my websites. It uses wrapper files to include the top and bottom portions, and reads an XML file to get the data to fill in the middle:
[%
title = "The Perl Review"
xml = "raw/xml/tpr_issues.xml"
sidebar = 1
%]
[% PROCESS top %]
<table class="content-table">
<tr>
<td colspan class="2">
<h2>Next issue: April 15</h2>
[% PERL %]
use XML::Twig;
my $twig = XML::Twig->new;
$twig->parsefile( $stash->get( 'xml' ) );
my $root = $twig->root;
my $latest_issue = $root->first_child( 'release' );
my( $volume, $issue, $year, $season ) =
map { eval {$latest_issue->first_child( $_ )->text } }
qw( volume issue year season );
my $articles = $latest_issue->first_child( 'articles' );
print <<"TEMPLATE";
<A class="cover-link" href="/Subscribers/ThePerlReview-v${volume}i${issue}.pdf"><img
class="cover-image-medium" height="396" width="306"
src="/Images/covers/v${volume}i${issue}-cover-medium.png" /></a>
</td>
<td class="article-cell">
<h2 id="issue-header">Issue $volume.$issue, $season $year</h2>
TEMPLATE
foreach my $article ( $articles->children( ) )
{
my @children = map { $_->tag } $article->children;
my %hash =
map {
$article->first_child( $_ )->tag,
$article->first_child( $_ )->text
}
map { $_->tag } $article->children;
print qq|\t<p class="article-title"><span class="article-title">$hash{title}</span>|;
print qq| (<a href="$hash{sample_page}">sample</a>)| if $hash{sample_page};
print "<br />\n";
print qq|\t\t<span class="article-author">$hash{author}</span></p>\n|;
}
[% END %]
[% PROCESS issue_note %]
</td>
</tr>
</table>
[% PROCESS footer %]
Upvotes: 1