summaryrefslogtreecommitdiff
path: root/lib/VNWeb
diff options
context:
space:
mode:
authorYorhel <git@yorhel.nl>2019-11-03 14:12:35 +0100
committerYorhel <git@yorhel.nl>2019-11-10 12:44:55 +0100
commitcc4607635279792b59953bba2e3cb4a3928e76df (patch)
tree227627601aa35df51e2ca10ff0006495bb933e9e /lib/VNWeb
parent6ae025a405ea6e40c37a183ba7f3a98c4d9e39cb (diff)
Reorganize JS and Elm instantiation + more efficient ulist loading
The order in which .js files are concatenated is (and always has been) important, so rather than relying on name order I've changed that to an explicit $JS_FILES list in the Makefile. Less convenient, but at least we have more freedom regarding .js file naming and organization now. Rather than encoding the Elm flags as JSON in 'data-' attributes, I've added a system for global page variables (pagevars) where the Elm flags are now stored separately from their HTML tags. This has the advantage of more efficient encoding (no more &quot;s), faster parsing (just a single JSON.parse()), and easier/more efficient modification of the Elm arguments from JS. The pagevars provide a unified way of passing other variables to JS as well, which I've used to deduplicate the list of labels on the new ulist page. That shaves off a good 40 KiB on the page size for a typical listing. Whether all of this actually improves the page loading time, I don't really know. Most of the slowness in Firefox seems to come from simply instantiating many <input time="date"> objects.
Diffstat (limited to 'lib/VNWeb')
-rw-r--r--lib/VNWeb/HTML.pm17
-rw-r--r--lib/VNWeb/User/Lists.pm11
2 files changed, 19 insertions, 9 deletions
diff --git a/lib/VNWeb/HTML.pm b/lib/VNWeb/HTML.pm
index 23432627..30813aac 100644
--- a/lib/VNWeb/HTML.pm
+++ b/lib/VNWeb/HTML.pm
@@ -33,6 +33,9 @@ our @EXPORT = qw/
/;
+# Encoded as JSON and appended to the end of the page, to be read by pagevars.js.
+my %pagevars;
+
# Ugly hack to move rendering down below the float object.
sub clearfloat_ { div_ class => 'clearfloat', '' }
@@ -93,10 +96,9 @@ sub user_displayname {
# Instantiate an Elm module
sub elm_ {
my($mod, $schema, $data, $placeholder) = @_;
- div_ 'data-elm-module' => $mod,
- $data ? (
- 'data-elm-flags' => JSON::XS->new->allow_nonref->encode($schema ? $schema->analyze->coerce_for_json($data, unknown => 'remove') : $data)
- ) : (), $placeholder//'';
+ $pagevars{elm} ||= [];
+ push $pagevars{elm}->@*, [ $mod, $data ? ($schema ? $schema->analyze->coerce_for_json($data, unknown => 'remove') : $data) : () ];
+ div_ id => "elm$#{$pagevars{elm}}", $placeholder//'';
}
@@ -282,6 +284,8 @@ sub _footer_ {
my $modules = uri_escape join "\n", sort keys %INC;
a_ href => 'data:text/plain,'.$modules, 'Modules';
+ lit_ ' | ';
+ debug_ \%pagevars;
}
}
@@ -394,6 +398,7 @@ sub _hidden_msg_ {
sub framework_ {
my $cont = pop;
my %o = @_;
+ %pagevars = $o{pagevars} ? $o{pagevars}->%* : ();
html_ lang => 'en', sub {
head_ sub { _head_ \%o };
@@ -406,6 +411,10 @@ sub framework_ {
$cont->() unless $o{hiddenmsg} && _hidden_msg_ \%o;
div_ id => 'footer', \&_footer_;
};
+ script_ type => 'application/json', id => 'pagevars', sub {
+ # Escaping rules for a JSON <script> context are kinda weird, but more efficient than regular xml_escape().
+ lit_(JSON::XS->new->canonical->encode(\%pagevars) =~ s{</}{<\\/}rg =~ s/<!--/<\\u0021--/rg);
+ } if keys %pagevars;
script_ type => 'application/javascript', src => config->{url_static}.'/f/v2rw.js?'.config->{version}, '';
}
}
diff --git a/lib/VNWeb/User/Lists.pm b/lib/VNWeb/User/Lists.pm
index 7d599536..2558963b 100644
--- a/lib/VNWeb/User/Lists.pm
+++ b/lib/VNWeb/User/Lists.pm
@@ -125,10 +125,7 @@ sub vn_ {
my @l = grep $l{$_->{id}} && $_->{id} != 7, @$labels;
my $txt = @l ? join ', ', map $_->{label}, @l : '-';
if($own) {
- # XXX: Copying the entire $labels list for each entry is rather inefficient, would be nice if we could store that globally.
- my @labels = grep $_->{id} != 7, @$labels;
- elm_ 'ULists.LabelEdit' => $VNLABELS_OUT,
- { uid => $uid, vid => $v->{id}, labels => \@labels, selected => [ grep $_ != 7, $v->{labels}->@* ] }, $txt;
+ elm_ 'ULists.LabelEdit' => $VNLABELS_OUT, { vid => $v->{id}, selected => [ grep $_ != 7, $v->{labels}->@* ] }, $txt;
} else {
txt_ $txt;
}
@@ -240,12 +237,16 @@ TUWF::get qr{/$RE{uid}/ulist}, sub {
my $title = $own ? 'My list' : user_displayname($u)."'s list";
framework_ title => $title, type => 'u', dbobj => $u, tab => 'list',
+ $own ? ( pagevars => {
+ uid => $u->{id}*1,
+ labels => $LABELS->analyze->{keys}{labels}->coerce_for_json($labels),
+ } ) : (),
sub {
my $opt;
div_ class => 'mainbox', sub {
h1_ $title;
$opt = filters_ $own, $labels;
- elm_ 'ULists.ManageLabels', $LABELS, { uid => $u->{id}, labels => $labels } if $own;
+ elm_ 'ULists.ManageLabels' if $own;
};
listing_ $u->{id}, $own, $opt, $labels;
};