mourningdove/cgi-bin/LJ/Widget/ThemeNav.pm

342 lines
12 KiB
Perl
Raw Permalink Normal View History

2026-05-24 01:03:05 +00:00
# This code was forked from the LiveJournal project owned and operated
# by Live Journal, Inc. The code has been modified and expanded by
# Dreamwidth Studios, LLC. These files were originally licensed under
# the terms of the license supplied by Live Journal, Inc, which can
# currently be found at:
#
# http://code.livejournal.org/trac/livejournal/browser/trunk/LICENSE-LiveJournal.txt
#
# In accordance with the original license, this code and all its
# modifications are provided under the GNU General Public License.
# A copy of that license can be found in the LICENSE file included as
# part of this distribution.
package LJ::Widget::ThemeNav;
use strict;
use base qw(LJ::Widget);
use Carp qw(croak);
use LJ::Customize;
sub ajax { 1 }
sub can_fake_ajax_post { 1 }
sub authas { 1 }
sub need_res { qw( stc/widgets/themenav.css js/6alib/inputcomplete.js ) }
sub render_body {
my $class = shift;
my %opts = @_;
my $u = $class->get_effective_remote();
die "Invalid user." unless LJ::isu($u);
my $theme_chooser_id = defined $opts{theme_chooser_id} ? $opts{theme_chooser_id} : 0;
my $headextra = $opts{headextra};
my $remote = LJ::get_remote();
my $getextra = $u->user ne $remote->user ? "?authas=" . $u->user : "";
my $getsep = $getextra ? "&" : "?";
# filter criteria
my $cat = defined $opts{cat} ? $opts{cat} : "";
my $layoutid = defined $opts{layoutid} ? $opts{layoutid} : 0;
my $designer = defined $opts{designer} ? $opts{designer} : "";
my $search = defined $opts{search} ? $opts{search} : "";
my $page = defined $opts{page} ? $opts{page} : 1;
my $show = defined $opts{show} ? $opts{show} : 12;
my $showarg = $show != 12 ? "show=$opts{show}" : "";
# we want to have "All" selected if we're filtering by layout or designer, or if we're searching
my $viewing_all = $layoutid || $designer || $search;
my $theme_chooser = LJ::Widget::ThemeChooser->new( id => $theme_chooser_id );
$theme_chooser_id = $theme_chooser->{id} unless $theme_chooser_id;
$$headextra .= $theme_chooser->wrapped_js( page_js_obj => "Customize" ) if $headextra;
# sort cats by specificed order key, then alphabetical order
my %cats = LJ::Customize->get_cats($u);
my @cats_sorted =
sort { $cats{$a}->{order} <=> $cats{$b}->{order} }
sort { lc $cats{$a}->{text} cmp lc $cats{$b}->{text} } keys %cats;
# pull the main cats out of the full list
my @main_cats_sorted;
for ( my $i = 0 ; $i < @cats_sorted ; $i++ ) {
my $c = $cats_sorted[$i];
if ( defined $cats{$c}->{main} ) {
my $el = splice( @cats_sorted, $i, 1 );
push @main_cats_sorted, $el;
$i--; # we just removed an element from @cats_sorted
}
}
my @keywords = LJ::Customize->get_search_keywords_for_js($u);
my $keywords_string = join( ",", @keywords );
my $upsell = LJ::Hooks::run_hook( 'customize_advanced_area_upsell', $u ) || '';
my $main_cat_list = $class->print_cat_list(
user => $u,
selected_cat => $cat,
viewing_all => $viewing_all,
cat_list => \@main_cats_sorted,
getextra => $getextra,
showarg => $showarg,
);
my $cat_list = $class->print_cat_list(
user => $u,
selected_cat => $cat,
viewing_all => $viewing_all,
cat_list => \@cats_sorted,
getextra => $getextra,
showarg => $showarg,
);
my $themechooser_html = $theme_chooser->render(
'cat' => $cat,
'layoutid' => $layoutid,
'designer' => $designer,
'search' => $search,
'page' => $page,
'show' => $show
);
my $vars = {
cat => $cat,
layoutid => $layoutid,
designer => $designer,
search => $search,
page => $page,
show => $show,
themechooser_html => $themechooser_html,
keywords_string => $keywords_string,
upsell => $upsell,
cats_sorted => \@cats_sorted,
main_cat_list => $main_cat_list,
cat_list => $cat_list
};
return DW::Template->template_string( 'widget/themenav.tt', $vars );
}
sub print_cat_list {
my $class = shift;
my %opts = @_;
my $u = $opts{user};
my $cat_list = $opts{cat_list};
my %cats = LJ::Customize->get_cats($u);
my @special_themes = LJ::S2Theme->load_by_cat("special");
my $special_themes_exist = 0;
foreach my $special_theme (@special_themes) {
my $layout_is_active =
LJ::Hooks::run_hook( "layer_is_active", $special_theme->layout_uniq );
my $theme_is_active = LJ::Hooks::run_hook( "layer_is_active", $special_theme->uniq );
if ( $layout_is_active && $theme_is_active ) {
$special_themes_exist = 1;
last;
}
}
my @custom_themes = LJ::S2Theme->load_by_user( $opts{user} );
my $ret;
for ( my $i = 0 ; $i < @$cat_list ; $i++ ) {
my $c = $cat_list->[$i];
next if $c eq "special" && !$special_themes_exist;
next if $c eq "custom" && !@custom_themes;
my $li_class = "";
$li_class .= " on"
if ( $c eq $opts{selected_cat} )
|| ( $c eq "featured" && !$opts{selected_cat} && !$opts{viewing_all} )
|| ( $c eq "all" && $opts{viewing_all} );
$li_class .= " first" if $i == 0;
$li_class .= " last" if $i == @$cat_list - 1;
$li_class =~ s/^\s//; # remove the first space
$li_class = " class='$li_class'" if $li_class;
my $arg = "";
$arg = "cat=$c" unless $c eq "featured";
if ( $arg || $opts{showarg} ) {
my $allargs = $arg;
$allargs .= "&" if $allargs && $opts{showarg};
$allargs .= $opts{showarg};
$arg = $opts{getextra} ? "&$allargs" : "?$allargs";
}
$ret .=
"<li$li_class><a href='$LJ::SITEROOT/customize/$opts{getextra}$arg' class='theme-nav-cat'>$cats{$c}->{text}</a></li>";
}
return $ret;
}
sub handle_post {
my $class = shift;
my $post = shift;
my %opts = @_;
my $q_string = BML::get_query_string();
$q_string =~ s/&?page=\d+//g;
my $url = "$LJ::SITEROOT/customize/";
if ( $post->{filter} ) {
$q_string = "?$q_string" if $q_string;
my $q_sep = $q_string ? "&" : "?";
$url .= $q_string;
}
elsif ( $post->{page} ) {
$q_string = "?$q_string" if $q_string;
my $q_sep = $q_string ? "&" : "?";
$post->{page} = LJ::eurl( $post->{page} );
if ( $post->{page} != 1 ) {
$url .= "$q_string${q_sep}page=$post->{page}";
}
else {
$url .= $q_string;
}
}
elsif ( $post->{show} ) {
$q_string =~ s/&?show=\w+//g;
$q_string = "?$q_string" if $q_string;
my $q_sep = $q_string ? "&" : "?";
$post->{show} = LJ::eurl( $post->{show} );
if ( $post->{show} != 12 ) {
$url .= "$q_string${q_sep}show=$post->{show}";
}
else {
$url .= $q_string;
}
}
elsif ( $post->{search} ) {
my $show = ( $q_string =~ /&?show=(\w+)/ ) ? "&show=$1" : "";
my $authas = ( $q_string =~ /&?authas=(\w+)/ ) ? "&authas=$1" : "";
$q_string = "";
$post->{search} = LJ::eurl( $post->{search} );
$url .= "?search=$post->{search}$authas$show";
}
return BML::redirect($url);
}
sub js {
q [
initWidget: function () {
var self = this;
if ($('search_box')) {
var keywords = new InputCompleteData(Customize.ThemeNav.searchwords, "ignorecase");
var ic = new InputComplete($('search_box'), keywords);
var text = "theme, layout, or designer";
var color = "#999";
$('search_box').style.color = color;
$('search_box').value = text;
DOM.addEventListener($('search_box'), "focus", function (evt) {
if ($('search_box').value == text) {
$('search_box').style.color = "";
$('search_box').value = "";
}
});
DOM.addEventListener($('search_box'), "blur", function (evt) {
if ($('search_box').value == "") {
$('search_box').style.color = color;
$('search_box').value = text;
}
});
}
// add event listener to the search form
DOM.addEventListener($('search_form'), "submit", function (evt) { self.filterThemes(evt, "search", $('search_box').value) });
var filter_links = DOM.getElementsByClassName(document, "theme-nav-cat");
// add event listeners to all of the category links
filter_links.forEach(function (filter_link) {
var evt_listener_added = 0;
var getArgs = LiveJournal.parseGetArgs(filter_link.href);
for (var arg in getArgs) {
if (!getArgs.hasOwnProperty(arg)) continue;
if (arg == "authas" || arg == "show") continue;
DOM.addEventListener(filter_link, "click", function (evt) { self.filterThemes(evt, arg, unescape( getArgs[arg] ) ) });
evt_listener_added = 1;
break;
}
// if there was no listener added to a link, add it without any args (for the 'featured' category)
if (!evt_listener_added) {
DOM.addEventListener(filter_link, "click", function (evt) { self.filterThemes(evt, "", "") });
}
});
},
filterThemes: function (evt, key, value) {
if (key == "show") {
// need to go back to page 1 if the show amount was switched because
// the current page may no longer have any themes to show on it
Customize.page = 1;
} else if (key != "page") {
Customize.resetFilters();
}
// do not do anything with a layoutid of 0
if (key == "layoutid" && value == 0) {
Event.stop(evt);
return;
}
if (key == "cat") Customize.cat = value;
if (key == "layoutid") Customize.layoutid = value;
if (key == "designer") Customize.designer = value;
if (key == "search") Customize.search = value;
if (key == "page") Customize.page = value;
if (key == "show") Customize.show = value;
this.updateContent({
method: "GET",
cat: Customize.cat,
layoutid: Customize.layoutid,
designer: Customize.designer,
search: Customize.search,
page: Customize.page,
show: Customize.show,
theme_chooser_id: $('theme_chooser_id').value
});
Event.stop(evt);
if (key == "search") {
$("search_btn").disabled = true;
} else if (key == "page" || key == "show") {
$("paging_msg_area_top").innerHTML = "<em>Please wait...</em>";
$("paging_msg_area_bottom").innerHTML = "<em>Please wait...</em>";
} else {
Customize.cursorHourglass(evt);
}
},
onData: function (data) {
Customize.CurrentTheme.updateContent({
show: Customize.show
});
Customize.hideHourglass();
},
onRefresh: function (data) {
this.initWidget();
Customize.ThemeChooser.initWidget();
}
];
}
1;