template attachments (scripts and stylesheets)
This commit is contained in:
parent
676b124697
commit
f4df3b1280
6 changed files with 664 additions and 36 deletions
|
|
@ -31,6 +31,7 @@ my $quiet;
|
|||
my $session = start();
|
||||
|
||||
# upgrade functions go here
|
||||
addTemplateAttachmentsTable($session);
|
||||
revertUsePacked( $session );
|
||||
|
||||
finish($session);
|
||||
|
|
@ -45,6 +46,22 @@ finish($session);
|
|||
# print "DONE!\n" unless $quiet;
|
||||
#}
|
||||
|
||||
sub addTemplateAttachmentsTable {
|
||||
my $session = shift;
|
||||
my $create = q{
|
||||
create table template_attachments (
|
||||
templateId varchar(22),
|
||||
revisionDate bigint(20),
|
||||
url varchar(256),
|
||||
type varchar(20),
|
||||
sequence int(11),
|
||||
|
||||
primary key (templateId, revisionDate, url)
|
||||
)
|
||||
};
|
||||
$session->db->write($create);
|
||||
}
|
||||
|
||||
#----------------------------------------------------------------------------
|
||||
# Rollback usePacked. It should be carefully applied manually for now
|
||||
sub revertUsePacked {
|
||||
|
|
|
|||
|
|
@ -19,9 +19,17 @@ use base 'WebGUI::Asset';
|
|||
use WebGUI::International;
|
||||
use WebGUI::Asset::Template::HTMLTemplate;
|
||||
use WebGUI::Utility;
|
||||
use WebGUI::Form;
|
||||
use Tie::IxHash;
|
||||
use Clone qw/clone/;
|
||||
use HTML::Packer;
|
||||
|
||||
tie my %attachmentTypeNames, 'Tie::IxHash' => (
|
||||
stylesheet => 'CSS Stylesheet',
|
||||
headScript => 'Javascript (head)',
|
||||
bodyScript => 'Javascript (body)',
|
||||
);
|
||||
|
||||
=head1 NAME
|
||||
|
||||
Package WebGUI::Asset::Template
|
||||
|
|
@ -43,6 +51,52 @@ These methods are available from this class:
|
|||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 addAttachments ( attachments )
|
||||
|
||||
Adds attachments to this template. Attachments is an arrayref of hashrefs,
|
||||
where each hashref should have at least url, type, and sequence as keys.
|
||||
|
||||
=cut
|
||||
|
||||
sub addAttachments {
|
||||
my ($self, $attachments) = @_;
|
||||
my $db = $self->session->db;
|
||||
|
||||
my $sql = q{
|
||||
INSERT INTO template_attachments
|
||||
(templateId, revisionDate, url, type, sequence)
|
||||
VALUES
|
||||
(?, ?, ?, ?, ?)
|
||||
};
|
||||
|
||||
foreach my $a (@$attachments) {
|
||||
my @params = (
|
||||
$self->getId,
|
||||
$self->get('revisionDate'),
|
||||
@{$a}{qw(url type sequence)}
|
||||
);
|
||||
$db->write($sql, \@params);
|
||||
}
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 addRevision ( )
|
||||
|
||||
Override the master addRevision to copy attachments
|
||||
|
||||
=cut
|
||||
|
||||
sub addRevision {
|
||||
my $self = shift;
|
||||
my $object = $self->SUPER::addRevision(@_);
|
||||
$object->addAttachments($self->getAttachments);
|
||||
|
||||
return $object;
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 definition ( session, definition )
|
||||
|
||||
Defines the properties of this asset.
|
||||
|
|
@ -146,6 +200,39 @@ sub duplicate {
|
|||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 removeAttachments ( urls )
|
||||
|
||||
Removes the specified attachments (specified by their urls, NOT by hashrefs,
|
||||
since urls are unique to a particular revision) from this template. urls
|
||||
should be an arrayref of strings.
|
||||
|
||||
=cut
|
||||
|
||||
sub removeAttachments {
|
||||
my ($self, $urls) = @_;
|
||||
|
||||
return unless @$urls;
|
||||
|
||||
my $db = $self->session->db;
|
||||
my $dbh = $db->dbh;
|
||||
my $in = join(',', map { $dbh->quote($_) } @$urls);
|
||||
my $rmsql = qq{
|
||||
DELETE FROM
|
||||
template_attachments
|
||||
WHERE
|
||||
templateId = ?
|
||||
AND revisionDate = ?
|
||||
AND url IN ($in)
|
||||
};
|
||||
my @params = (
|
||||
$self->getId,
|
||||
$self->get('revisionDate'),
|
||||
);
|
||||
$db->write($rmsql, \@params);
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 packTemplate ( template )
|
||||
|
||||
Pack the template into a minified version for faster downloads.
|
||||
|
|
@ -185,11 +272,76 @@ sub processPropertiesFromFormPost {
|
|||
$needsUpdate = 1;
|
||||
$data{extraHeadTags} = '';
|
||||
}
|
||||
|
||||
my $f = $self->session->form;
|
||||
my $p = $f->paramsHashRef;
|
||||
my @nums = grep {$_} map { my ($i) = /^attachmentUrl(\d+)$/; $i } keys %$p;
|
||||
my @add;
|
||||
|
||||
foreach my $n (@nums) {
|
||||
my ($index, $type, $url) =
|
||||
map { $f->process('attachment' . $_ . $n) }
|
||||
qw(Index Type Url);
|
||||
|
||||
push(
|
||||
@add, {
|
||||
sequence => $index,
|
||||
url => $url,
|
||||
type => $type,
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
my @remove = $f->process('removeAttachment', 'list');
|
||||
$data{removeAttachments} = \@remove;
|
||||
$data{attachments} = \@add;
|
||||
|
||||
$needsUpdate = 1 if @remove || @add;
|
||||
|
||||
$self->update(\%data) if $needsUpdate;
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 getAttachments ( [type] )
|
||||
|
||||
Returns an arrayref of hashrefs representing all attachments for this template
|
||||
of the specified type (link, bodyScript, headScript).
|
||||
|
||||
=head3 type
|
||||
|
||||
If defined, will limit the attachments to this type; e.g., passing
|
||||
'stylesheet' will return only stylesheets.
|
||||
|
||||
=cut
|
||||
|
||||
sub getAttachments {
|
||||
my ( $self, $type ) = @_;
|
||||
my @params = ($self->getId, $self->get('revisionDate'));
|
||||
my $typeString;
|
||||
|
||||
if ($type) {
|
||||
$typeString = 'AND type = ?';
|
||||
push(@params, $type);
|
||||
}
|
||||
|
||||
my $sql = qq{
|
||||
SELECT
|
||||
*
|
||||
FROM
|
||||
template_attachments
|
||||
WHERE
|
||||
templateId = ?
|
||||
AND revisionDate = ?
|
||||
$typeString
|
||||
ORDER BY
|
||||
type, sequence ASC
|
||||
};
|
||||
return $self->session->db->buildArrayRefOfHashRefs($sql, \@params);
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 getEditForm ( )
|
||||
|
||||
Returns the TabForm object that will be used in generating the edit page for this asset.
|
||||
|
|
@ -230,11 +382,11 @@ sub getEditForm {
|
|||
-label=>$i18n->get('show in forms'),
|
||||
-hoverHelp=>$i18n->get('show in forms description'),
|
||||
);
|
||||
$tabform->getTab("properties")->codearea(
|
||||
$tabform->getTab("properties")->codearea(
|
||||
-name=>"template",
|
||||
-label=>$i18n->get('assetName'),
|
||||
-hoverHelp=>$i18n->get('template description'),
|
||||
-syntax => "html",
|
||||
-syntax => "html",
|
||||
-value=>$self->getValue("template")
|
||||
);
|
||||
$tabform->getTab('properties')->yesNo(
|
||||
|
|
@ -257,8 +409,67 @@ sub getEditForm {
|
|||
-value=>$value,
|
||||
-label=>$i18n->get('parser'),
|
||||
-hoverHelp=>$i18n->get('parser description'),
|
||||
);
|
||||
);
|
||||
}
|
||||
|
||||
my $session = $self->session;
|
||||
my @headers = map { '<th>' . $i18n->get("attachment header $_") . '</th>' }
|
||||
qw(index type url remove);
|
||||
|
||||
my $table = '<table id="attachmentDisplay">';
|
||||
$table .= "<thead><tr>@headers</tr></thead><tbody id='addAnchor'>";
|
||||
foreach my $a ( @{ $self->getAttachments } ) {
|
||||
my ($seq, $type, $url) = @{$a}{qw(sequence type url)};
|
||||
# escape macros in the url so they don't get processed
|
||||
$url =~ s/\^/^/g;
|
||||
my $del = WebGUI::Form::checkbox(
|
||||
$session, {
|
||||
name => 'removeAttachment',
|
||||
value => $url,
|
||||
extras => 'class="id"',
|
||||
}
|
||||
);
|
||||
my @data = (
|
||||
"<td class='index'>$seq</td>",
|
||||
"<td class='type'>$type</td>",
|
||||
"<td class='url'>$url</td>",
|
||||
"<td>$del</td>",
|
||||
);
|
||||
$table .= "<tr class='existingAttachment'>@data</tr>";
|
||||
}
|
||||
$table .= '</tbody></table>';
|
||||
my $properties = $tabform->getTab('properties');
|
||||
my $label = $i18n->get('attachment display label');
|
||||
$properties->raw("<tr><td>$label</td><td>$table</td></tr>");
|
||||
|
||||
my @data = map { "<td>$_</td>" } (
|
||||
WebGUI::Form::integer(
|
||||
$session, { size => '2', id => 'addBoxIndex' }
|
||||
),
|
||||
WebGUI::Form::selectBox(
|
||||
$session, { options => \%attachmentTypeNames, id => 'addBoxType' }
|
||||
),
|
||||
WebGUI::Form::text($session, { id => 'addBoxUrl', size => 40 }),
|
||||
WebGUI::Form::button(
|
||||
$session, {
|
||||
value => $i18n->get('attachment add button'),
|
||||
extras => 'onclick="addClick()"'
|
||||
}
|
||||
),
|
||||
);
|
||||
|
||||
my ($style, $url) = $self->session->quick(qw(style url));
|
||||
$style->setScript($url->extras('yui/build/yahoo/yahoo-min.js'));
|
||||
$style->setScript($url->extras('yui/build/json/json-min.js'));
|
||||
$style->setScript($url->extras('yui/build/dom/dom-min.js'));
|
||||
|
||||
pop(@headers);
|
||||
my $scriptUrl = $url->extras('templateAttachments.js');
|
||||
$table = "<table id='addBox'><tr>@headers</tr><tr>@data</tr></table>";
|
||||
$table .= qq(<script type="text/javascript" src="$scriptUrl"></script>);
|
||||
$label = $i18n->get('attachment add field label');
|
||||
$properties->raw("<tr><td>$label</td><td>$table</td></tr>");
|
||||
|
||||
return $tabform;
|
||||
}
|
||||
|
||||
|
|
@ -370,15 +581,42 @@ A hash reference containing template variables to be processed for the head bloc
|
|||
|
||||
sub prepare {
|
||||
my $self = shift;
|
||||
my $vars = shift;
|
||||
my $vars = shift;
|
||||
$self->{_prepared} = 1;
|
||||
my $templateHeadersSent = $self->session->stow->get("templateHeadersSent") || [];
|
||||
my @sent = @{$templateHeadersSent};
|
||||
unless (isIn($self->getId, @sent)) { # don't send head block if we've already sent it for this template
|
||||
$self->session->style->setRawHeadTags($self->getParser($self->session, $self->get('parser'))->process($self->getExtraHeadTags, $vars));
|
||||
}
|
||||
push(@sent, $self->getId);
|
||||
$self->session->stow->set("templateHeadersSent", \@sent);
|
||||
|
||||
my $sent = $self->session->stow->get('templateHeadersSent');
|
||||
unless ($sent) {
|
||||
$self->session->stow->set('templateHeadersSent', $sent = []);
|
||||
}
|
||||
|
||||
my $id = $self->getId;
|
||||
# don't send head block if we've already sent it for this template
|
||||
return if isIn($id, @$sent);
|
||||
|
||||
my $session = $self->session;
|
||||
my ($db, $style) = $session->quick(qw(db style));
|
||||
my $parser = $self->getParser($session, $self->get('parser'));
|
||||
my $headBlock = $parser->process($self->getExtraHeadTags, $vars);
|
||||
|
||||
$style->setRawHeadTags($headBlock);
|
||||
|
||||
foreach my $sheet ( @{ $self->getAttachments('stylesheet') } ) {
|
||||
my %props = ( type => 'text/css', rel => 'stylesheet' );
|
||||
$style->setLink($sheet->{url}, \%props);
|
||||
}
|
||||
|
||||
my $doScripts = sub {
|
||||
my ($type, $body) = @_;
|
||||
foreach my $script ( @{ $self->getAttachments($type) } ) {
|
||||
my %props = ( type => 'text/javascript' );
|
||||
$style->setScript($script->{url}, \%props, $body);
|
||||
}
|
||||
};
|
||||
|
||||
$doScripts->('headScript');
|
||||
$doScripts->('bodyScript', 1);
|
||||
|
||||
push(@$sent, $id);
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -445,6 +683,27 @@ sub processRaw {
|
|||
return $class->getParser($session,$parser)->process($template, $vars);
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 purgeRevision ( )
|
||||
|
||||
Override the master purgeRevision to purge attachments
|
||||
|
||||
=cut
|
||||
|
||||
sub purgeRevision {
|
||||
my $self = shift;
|
||||
my $db = $self->session->db;
|
||||
my $sql = q{
|
||||
DELETE FROM
|
||||
template_attachments
|
||||
WHERE
|
||||
templateId = ?
|
||||
AND revisionDate = ?
|
||||
};
|
||||
$db->write($sql, [$self->getId, $self->get('revisionDate')]);
|
||||
return $self->SUPER::purgeRevision(@_);
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
|
|
@ -456,16 +715,27 @@ packages that contain headBlocks.
|
|||
This method is deprecated and will be removed in the future. Don't plan
|
||||
on this being here.
|
||||
|
||||
Note, we are also using this now to update template attachments. So maybe it
|
||||
will stay.
|
||||
|
||||
=cut
|
||||
|
||||
sub update {
|
||||
my $self = shift;
|
||||
my $requestedProperties = shift;
|
||||
my $properties = clone($requestedProperties);
|
||||
|
||||
my $attachments = delete $properties->{attachments} || [];
|
||||
my $removeAttachments = delete $properties->{removeAttachments} || [];
|
||||
|
||||
$self->removeAttachments($removeAttachments);
|
||||
$self->addAttachments($attachments);
|
||||
|
||||
if (exists $properties->{headBlock}) {
|
||||
$properties->{extraHeadTags} .= $properties->{headBlock};
|
||||
delete $properties->{headBlock};
|
||||
}
|
||||
|
||||
$self->SUPER::update($properties);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -67,6 +67,30 @@ sub DESTROY {
|
|||
undef $self;
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
sub _generateAdditionalTags {
|
||||
my $var = shift;
|
||||
return sub {
|
||||
my $self = shift;
|
||||
my $tags = $self->{$var};
|
||||
delete $self->{$var};
|
||||
WebGUI::Macro::process($self->session,\$tags);
|
||||
return $tags;
|
||||
};
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 generateAdditionalBodyTags ( )
|
||||
|
||||
Creates tags that were set using setScript (if inBody was true) and setRawBodyTags.
|
||||
Macros are processed in the tags if processed by this method.
|
||||
|
||||
=cut
|
||||
|
||||
BEGIN { *generateAdditionalBodyTags = _generateAdditionalTags('_rawBody') }
|
||||
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
|
|
@ -77,15 +101,7 @@ Macros are processed in the tags if processed by this method.
|
|||
|
||||
=cut
|
||||
|
||||
sub generateAdditionalHeadTags {
|
||||
my $self = shift;
|
||||
my $tags = $self->{_raw};
|
||||
delete $self->{_raw};
|
||||
WebGUI::Macro::process($self->session,\$tags);
|
||||
return $tags;
|
||||
}
|
||||
|
||||
|
||||
BEGIN { *generateAdditionalHeadTags = _generateAdditionalTags('_raw') }
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
|
|
@ -196,10 +212,16 @@ if ($self->session->user->isRegistered || $self->session->setting->get("preventP
|
|||
} else {
|
||||
$var{'head.tags'} .= '<meta http-equiv="Cache-Control" content="must-revalidate" />'
|
||||
}
|
||||
|
||||
# Removing the newlines will probably annoy people.
|
||||
# Perhaps turn it off under debug mode?
|
||||
$var{'head.tags'} =~ s/\n//g;
|
||||
|
||||
# head.tags = head_attachments . body_attachments
|
||||
# keeping head.tags for backwards compatibility
|
||||
$var{'head_attachments'} = $var{'head.tags'};
|
||||
$var{'head.tags'} .= ($var{'body_attachments'} = '<!--morebody-->');
|
||||
|
||||
my $style = WebGUI::Asset::Template->new($self->session,$templateId);
|
||||
my $output;
|
||||
if (defined $style) {
|
||||
|
|
@ -216,8 +238,10 @@ if ($self->session->user->isRegistered || $self->session->setting->get("preventP
|
|||
}
|
||||
WebGUI::Macro::process($self->session,\$output);
|
||||
$self->sent(1);
|
||||
my $macroHeadTags = $self->generateAdditionalHeadTags();
|
||||
$output =~ s/\<\!--morehead--\>/$macroHeadTags/;
|
||||
my $macroHeadTags = $self->generateAdditionalHeadTags();
|
||||
my $macroBodyTags = $self->generateAdditionalBodyTags();
|
||||
$output =~ s/\<\!--morehead--\>/$macroHeadTags/;
|
||||
$output =~ s/\<\!--morebody--\>/$macroBodyTags/;
|
||||
return $output;
|
||||
}
|
||||
|
||||
|
|
@ -339,7 +363,33 @@ sub setMeta {
|
|||
$self->setRawHeadTags($tag);
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
sub _setRawTags {
|
||||
my $var = shift;
|
||||
return sub {
|
||||
my $self = shift;
|
||||
my $tags = shift;
|
||||
if ($self->sent) {
|
||||
$self->session->output->print($tags);
|
||||
}
|
||||
else {
|
||||
$self->{$var} .= $tags;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 setRawBodyTags ( tags )
|
||||
|
||||
Does exactly the same thing as setRawHeadTags, except that the tags will be
|
||||
appended to a seperate variable (to be output after the body if the style
|
||||
template supports it) instead.
|
||||
|
||||
=cut
|
||||
|
||||
BEGIN { *setRawBodyTags = _setRawTags('_rawBody') }
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
|
|
@ -357,21 +407,11 @@ A raw string containing tags. This is just a raw string so you must actually pas
|
|||
|
||||
=cut
|
||||
|
||||
sub setRawHeadTags {
|
||||
my $self = shift;
|
||||
my $tags = shift;
|
||||
if ($self->sent) {
|
||||
$self->session->output->print($tags);
|
||||
}
|
||||
else {
|
||||
$self->{_raw} .= $tags;
|
||||
}
|
||||
}
|
||||
|
||||
BEGIN { *setRawHeadTags = _setRawTags('_raw') }
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 setScript ( url, params )
|
||||
=head2 setScript ( url, params, [inBody] )
|
||||
|
||||
Sets a <script> tag into the <head> of this rendered page for this
|
||||
page view. This is typically used for dynamically adding references
|
||||
|
|
@ -388,12 +428,18 @@ The URL to your script.
|
|||
|
||||
A hash reference containing the additional parameters to include in the script tag, such as "type" and "language".
|
||||
|
||||
=head3 inBody
|
||||
|
||||
Optional, defaults to false. If true, the script will be added to the
|
||||
body_attachments variable instead of to head_attachments.
|
||||
|
||||
=cut
|
||||
|
||||
sub setScript {
|
||||
my $self = shift;
|
||||
my $url = shift;
|
||||
my $params = shift;
|
||||
my $inBody = shift;
|
||||
return undef if ($self->{_javascript}{$url});
|
||||
my $tag = '<script src="'.$url.'"';
|
||||
foreach my $name (keys %{$params}) {
|
||||
|
|
@ -401,7 +447,12 @@ sub setScript {
|
|||
}
|
||||
$tag .= '></script>'."\n";
|
||||
$self->{_javascript}{$url} = 1;
|
||||
$self->setRawHeadTags($tag);
|
||||
if ($inBody) {
|
||||
$self->setRawBodyTags($tag);
|
||||
}
|
||||
else {
|
||||
$self->setRawHeadTags($tag);
|
||||
}
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
|
|
|||
|
|
@ -298,6 +298,48 @@ Any scratch variables will be available in the template with this syntax:<br/>
|
|||
context => q{Label for URL to make a duplicate and open the duplicate's edit screen},
|
||||
},
|
||||
|
||||
'attachment header index' => {
|
||||
message => 'Index',
|
||||
lastUpdated => 1241192473,
|
||||
context => q|header for the sequence number column for attachments|,
|
||||
},
|
||||
|
||||
'attachment header type' => {
|
||||
message => 'Type',
|
||||
lastUpdated => 1241192473,
|
||||
context => q|header for the attachment types column|,
|
||||
},
|
||||
|
||||
'attachment header url' => {
|
||||
message => 'Url',
|
||||
lastUpdated => 1241192473,
|
||||
context => q|header for the url column for attachments|,
|
||||
},
|
||||
|
||||
'attachment header remove' => {
|
||||
message => 'Remove',
|
||||
lastUpdated => 1241192473,
|
||||
context => q|header for the remove button column for attachments|,
|
||||
},
|
||||
|
||||
'attachment display label' => {
|
||||
message => 'Attachments',
|
||||
lastUpdated => 1241192473,
|
||||
context => q|field label for displaying existing attachments|,
|
||||
},
|
||||
|
||||
'attachment add field label' => {
|
||||
message => 'Add Attachments',
|
||||
lastUpdated => 1241192473,
|
||||
context => q|field label for adding new attachments|,
|
||||
},
|
||||
|
||||
'attachment add button' => {
|
||||
message => 'Add',
|
||||
lastUpdated => 1241192473,
|
||||
context => q|button text for adding a new attachment|,
|
||||
},
|
||||
|
||||
'usePacked label' => {
|
||||
message => q{Use Packed Template},
|
||||
lastUpdated => 0,
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@ use lib "$FindBin::Bin/../lib";
|
|||
use WebGUI::Test;
|
||||
use WebGUI::Session;
|
||||
use WebGUI::Asset::Template;
|
||||
use Test::More tests => 15; # increment this value for each test you create
|
||||
use Test::More tests => 32; # increment this value for each test you create
|
||||
use Test::Deep;
|
||||
|
||||
my $session = WebGUI::Test->session;
|
||||
|
|
@ -67,6 +67,51 @@ my $template3 = $importNode->addChild({
|
|||
ok(!$template3->get('headBlock'), 'headBlock is empty');
|
||||
is($template3->get('extraHeadTags'), 'tag1 tag2 tag3', 'extraHeadTags contains headBlock info');
|
||||
|
||||
my @atts = (
|
||||
{type => 'headScript', sequence => 1, url => 'bar'},
|
||||
{type => 'headScript', sequence => 0, url => 'foo'},
|
||||
{type => 'stylesheet', sequence => 0, url => 'style'},
|
||||
{type => 'bodyScript', sequence => 0, url => 'body'},
|
||||
);
|
||||
|
||||
$template3->addAttachments(\@atts);
|
||||
my $att3 = $template3->getAttachments('headScript');
|
||||
is($att3->[0]->{url}, 'foo', 'has foo');
|
||||
is($att3->[1]->{url}, 'bar', 'has bar');
|
||||
is(@$att3, 2, 'proper size');
|
||||
|
||||
$template3->prepare;
|
||||
ok(exists $session->style->{_link}->{style}, 'style in style');
|
||||
ok(exists $session->style->{_javascript}->{$_}, "$_ in style") for qw(foo bar body);
|
||||
|
||||
# revision-ness of attachments
|
||||
|
||||
# sleep so the revisiondate isn't duplicated
|
||||
sleep 1;
|
||||
|
||||
my $template3rev = $template3->addRevision();
|
||||
my $att4 = $template3rev->getAttachments('headScript');
|
||||
is($att4->[0]->{url}, 'foo', 'rev has foo');
|
||||
is($att4->[1]->{url}, 'bar', 'rev has bar');
|
||||
is(@$att4, 2, 'rev is proper size');
|
||||
|
||||
$template3rev->addAttachments([{type => 'headScript', sequence => 2, url => 'baz'}]);
|
||||
$att4 = $template3rev->getAttachments('headScript');
|
||||
$att3 = $template3->getAttachments('headScript');
|
||||
is($att3->[0]->{url}, 'foo', 'original still has foo');
|
||||
is($att3->[1]->{url}, 'bar', 'original still has bar');
|
||||
is(@$att3, 2, 'original does not have new thing');
|
||||
|
||||
is($att4->[0]->{url}, 'foo', 'rev still has foo');
|
||||
is($att4->[1]->{url}, 'bar', 'rev still has bar');
|
||||
is($att4->[2]->{url}, 'baz', 'rev does have new thing');
|
||||
is(@$att4, 3, 'rev is proper size');
|
||||
|
||||
$template3rev->purgeRevision();
|
||||
|
||||
|
||||
# done checking revision stuff
|
||||
|
||||
$template->purge;
|
||||
$templateCopy->purge;
|
||||
$template3->purge;
|
||||
|
|
|
|||
203
www/extras/templateAttachments.js
Normal file
203
www/extras/templateAttachments.js
Normal file
|
|
@ -0,0 +1,203 @@
|
|||
// Really only used by the Template editor, but it doesn't belong in perl
|
||||
// code. It's too long.
|
||||
|
||||
var addClick = (function() {
|
||||
var uniqueId = 1;
|
||||
var count = 0;
|
||||
var urls = {};
|
||||
var types = {};
|
||||
var originals = {};
|
||||
var addAnchor = document.getElementById('addAnchor');
|
||||
var displayTable = document.getElementById('attachmentDisplay');
|
||||
|
||||
var nodes = {
|
||||
table: '',
|
||||
index: 'Index',
|
||||
type: 'Type',
|
||||
url: 'Url'
|
||||
};
|
||||
|
||||
function init() {
|
||||
displayTable.style.display = 'none';
|
||||
|
||||
for (var k in nodes) {
|
||||
var id = 'addBox' + nodes[k];
|
||||
nodes[k] = document.getElementById(id);
|
||||
}
|
||||
|
||||
var opts = nodes.type.options;
|
||||
for (var i = 0; i < opts.length; i++) {
|
||||
var o = opts[i];
|
||||
types[o.value] = o.text;
|
||||
}
|
||||
|
||||
var query = YAHOO.util.Dom.getElementsByClassName;
|
||||
var existing = query('existingAttachment', 'tr');
|
||||
for (var i = 0; i < existing.length; i++) {
|
||||
var node = existing[i];
|
||||
var d = {
|
||||
index: query('index', 'td', node)[0].innerHTML,
|
||||
type: query('type', 'td', node)[0].innerHTML,
|
||||
url: query('url', 'td', node)[0].innerHTML
|
||||
};
|
||||
originals[d.url] = true;
|
||||
add(d);
|
||||
node.parentNode.removeChild(node);
|
||||
}
|
||||
}
|
||||
|
||||
// When an original box gets changed, we should insert a removal node and
|
||||
// name the fields so that we remove the old and insert the new.
|
||||
function updater(u) {
|
||||
return function() {
|
||||
obj = urls[u];
|
||||
obj.index.onchange = null;
|
||||
obj.type.onchange = null;
|
||||
insertHidden(u);
|
||||
nameFields(u);
|
||||
};
|
||||
}
|
||||
|
||||
// Give the fields for an attachment entry some names so that they'll get
|
||||
// posted to the backend.
|
||||
function nameFields(u) {
|
||||
var id = uniqueId++;
|
||||
var obj = urls[u];
|
||||
obj.index.name = 'attachmentIndex' + id;
|
||||
obj.type.name = 'attachmentType' + id;
|
||||
obj.url.name = 'attachmentUrl' + id;
|
||||
}
|
||||
|
||||
// Insert a hidden input field in the form so that the backend knows to
|
||||
// remove one of the original attachments
|
||||
function insertHidden(u) {
|
||||
var tr = urls[u].tr;
|
||||
var hid = document.createElement('input');
|
||||
hid.type = 'hidden';
|
||||
hid.name = 'removeAttachment';
|
||||
hid.value = u;
|
||||
tr.parentNode.appendChild(hid);
|
||||
delete originals[u];
|
||||
}
|
||||
|
||||
// Make a function which will remove an attachment (remove the table row
|
||||
// and insertHidden if necesary)
|
||||
function remover(u) {
|
||||
return function() {
|
||||
var tr = urls[u].tr;
|
||||
|
||||
if (originals[u]) {
|
||||
insertHidden(u);
|
||||
}
|
||||
|
||||
tr.parentNode.removeChild(tr);
|
||||
delete urls[u];
|
||||
|
||||
if (--count == 0) {
|
||||
displayTable.style.display = 'none';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Add a new attachment (proper table row, etc). Attachments that already
|
||||
// existed (originals) will have unnamed fields so they don't get posted
|
||||
// to the backend.
|
||||
function add(d) {
|
||||
if (urls[d.url]) {
|
||||
alert('Already attached!');
|
||||
return;
|
||||
}
|
||||
|
||||
if (++count == 1) {
|
||||
displayTable.style.display = 'block';
|
||||
}
|
||||
|
||||
var index = document.createElement('input');
|
||||
index.size = 2;
|
||||
index.value = d.index;
|
||||
|
||||
var type = document.createElement('select');
|
||||
|
||||
for (var k in types) {
|
||||
var o = document.createElement('option');
|
||||
o.value = k;
|
||||
o.text = types[k];
|
||||
if (k == d.type) {
|
||||
o.selected = true;
|
||||
}
|
||||
type.appendChild(o);
|
||||
}
|
||||
|
||||
var url = document.createElement('input');
|
||||
url.size = 40;
|
||||
|
||||
var update = updater(d.url);
|
||||
url.value = d.url;
|
||||
url.oldValue = d.url;
|
||||
url.onchange = function() {
|
||||
var newValue = url.value;
|
||||
var oldValue = url.oldValue;
|
||||
if (urls[newValue]) {
|
||||
url.value = oldValue;
|
||||
alert('Already attached!');
|
||||
}
|
||||
else {
|
||||
url.oldValue = newValue;
|
||||
var d = urls[oldValue];
|
||||
if (originals[oldValue]) {
|
||||
update();
|
||||
}
|
||||
|
||||
delete urls[oldValue];
|
||||
urls[newValue] = d;
|
||||
}
|
||||
};
|
||||
|
||||
var btn = document.createElement('input');
|
||||
btn.type = 'button';
|
||||
btn.value = 'Remove';
|
||||
btn.onclick = remover(d.url);
|
||||
|
||||
var tr = document.createElement('tr');
|
||||
var data = [index, type, url, btn];
|
||||
for (var i = 0; i < data.length; i++) {
|
||||
var td = document.createElement('td');
|
||||
td.appendChild(data[i]);
|
||||
tr.appendChild(td);
|
||||
}
|
||||
|
||||
urls[d.url] = {
|
||||
tr : tr,
|
||||
index : index,
|
||||
type : type,
|
||||
url : url,
|
||||
};
|
||||
|
||||
if (originals[d.url]) {
|
||||
// url's is already taken care of above
|
||||
index.onchange = update;
|
||||
type.onchange = update;
|
||||
}
|
||||
else {
|
||||
nameFields(d.url);
|
||||
}
|
||||
|
||||
addAnchor.appendChild(tr);
|
||||
}
|
||||
|
||||
init();
|
||||
return function() {
|
||||
var d = {
|
||||
index: nodes.index.value,
|
||||
type: nodes.type.value,
|
||||
url: nodes.url.value
|
||||
};
|
||||
|
||||
d.url = d.url.replace(/^\s+|\s+$/g, '')
|
||||
if (d.url == '') {
|
||||
alert('No url!');
|
||||
return;
|
||||
}
|
||||
add(d);
|
||||
};
|
||||
})();
|
||||
Loading…
Add table
Add a link
Reference in a new issue