310 lines
12 KiB
Perl
310 lines
12 KiB
Perl
|
|
# 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::ThemeChooser;
|
||
|
|
|
||
|
|
use strict;
|
||
|
|
use base qw(LJ::Widget);
|
||
|
|
use Carp qw(croak);
|
||
|
|
use LJ::S2Theme;
|
||
|
|
use LJ::Customize;
|
||
|
|
|
||
|
|
sub ajax { 1 }
|
||
|
|
sub authas { 1 }
|
||
|
|
sub need_res { qw( stc/widgets/themechooser.css ) }
|
||
|
|
sub need_res_opts { priority => $LJ::OLD_RES_PRIORITY }
|
||
|
|
|
||
|
|
sub render_body {
|
||
|
|
my $class = shift;
|
||
|
|
my %opts = @_;
|
||
|
|
|
||
|
|
my $u = $class->get_effective_remote();
|
||
|
|
die "Invalid user." unless LJ::isu($u);
|
||
|
|
|
||
|
|
my $remote = LJ::get_remote();
|
||
|
|
my $getextra = $u->user ne $remote->user ? "?authas=" . $u->user : "";
|
||
|
|
my $getsep = $getextra ? "&" : "?";
|
||
|
|
my %cats = LJ::Customize->get_cats($u);
|
||
|
|
|
||
|
|
warn %opts;
|
||
|
|
|
||
|
|
# filter criteria
|
||
|
|
$opts{cat} //= "";
|
||
|
|
$opts{layoutid} //= 0;
|
||
|
|
$opts{designer} //= "";
|
||
|
|
$opts{search} //= "";
|
||
|
|
$opts{page} //= 1;
|
||
|
|
$opts{show} //= 12;
|
||
|
|
|
||
|
|
if ( $u->user ne $remote->user ) {
|
||
|
|
$opts{authas} = $u->user;
|
||
|
|
}
|
||
|
|
|
||
|
|
my $cat_title;
|
||
|
|
my @themes;
|
||
|
|
my $current = LJ::Customize->get_current_theme($u);
|
||
|
|
|
||
|
|
if ( $opts{cat} eq "all" ) {
|
||
|
|
@themes = LJ::S2Theme->load_all($u);
|
||
|
|
$cat_title = LJ::Lang::ml('widget.themechooser.header.all');
|
||
|
|
}
|
||
|
|
elsif ( $opts{cat} eq "custom" ) {
|
||
|
|
@themes = LJ::S2Theme->load_by_user($u);
|
||
|
|
$cat_title = LJ::Lang::ml('widget.themechooser.header.custom');
|
||
|
|
}
|
||
|
|
elsif ( $opts{cat} eq "base" ) {
|
||
|
|
@themes = LJ::S2Theme->load_default_themes();
|
||
|
|
$cat_title = $cats{'base'}->{text};
|
||
|
|
}
|
||
|
|
elsif ( $opts{cat} ) {
|
||
|
|
@themes = LJ::S2Theme->load_by_cat( $opts{cat} );
|
||
|
|
my $cat = $opts{cat};
|
||
|
|
$cat_title = $cats{$cat}->{text};
|
||
|
|
}
|
||
|
|
elsif ( $opts{layoutid} ) {
|
||
|
|
@themes = LJ::S2Theme->load_by_layoutid( $opts{layoutid}, $u );
|
||
|
|
my $layout_name = LJ::Customize->get_layout_name( $opts{layoutid}, user => $u );
|
||
|
|
$cat_title = LJ::ehtml($layout_name);
|
||
|
|
}
|
||
|
|
elsif ( $opts{designer} ) {
|
||
|
|
@themes = LJ::S2Theme->load_by_designer( $opts{designer} );
|
||
|
|
$cat_title = LJ::ehtml( $opts{designer} );
|
||
|
|
}
|
||
|
|
elsif ( $opts{search} ) {
|
||
|
|
@themes = LJ::S2Theme->load_by_search( $opts{search}, $u );
|
||
|
|
$cat_title = LJ::Lang::ml( 'widget.themechooser.header.search',
|
||
|
|
{ 'term' => LJ::ehtml( $opts{search} ) } );
|
||
|
|
}
|
||
|
|
else { # category is "featured"
|
||
|
|
@themes = LJ::S2Theme->load_by_cat("featured");
|
||
|
|
$cat_title = $cats{'featured'}->{text};
|
||
|
|
}
|
||
|
|
|
||
|
|
if ( $opts{cat} eq "base" ) {
|
||
|
|
|
||
|
|
# sort alphabetically by layout
|
||
|
|
@themes = sort { lc $a->layout_name cmp lc $b->layout_name } @themes;
|
||
|
|
}
|
||
|
|
else {
|
||
|
|
# sort themes with custom at the end, then alphabetically by theme
|
||
|
|
@themes =
|
||
|
|
sort { $a->is_custom <=> $b->is_custom }
|
||
|
|
sort { lc $a->name cmp lc $b->name } @themes;
|
||
|
|
}
|
||
|
|
|
||
|
|
# remove any themes from the array that are not defined or whose layout or theme is not active
|
||
|
|
for ( my $i = 0 ; $i < @themes ; $i++ ) {
|
||
|
|
my $layout_is_active = LJ::Hooks::run_hook( "layer_is_active", $themes[$i]->layout_uniq );
|
||
|
|
my $theme_is_active = LJ::Hooks::run_hook( "layer_is_active", $themes[$i]->uniq );
|
||
|
|
|
||
|
|
unless ( ( defined $themes[$i] )
|
||
|
|
&& ( !defined $layout_is_active || $layout_is_active )
|
||
|
|
&& ( !defined $theme_is_active || $theme_is_active ) )
|
||
|
|
{
|
||
|
|
|
||
|
|
splice( @themes, $i, 1 );
|
||
|
|
$i--; # we just removed an element from @themes
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
@themes = LJ::Customize->remove_duplicate_themes(@themes);
|
||
|
|
my $max_page =
|
||
|
|
$opts{show} ne "all" ? POSIX::ceil( scalar(@themes) / $opts{show} ) || 1 : 1;
|
||
|
|
|
||
|
|
if ( $opts{show} ne "all" ) {
|
||
|
|
my $i_first = $opts{show} * ( $opts{page} - 1 );
|
||
|
|
my $i_last = ( $opts{show} * $opts{page} ) - 1;
|
||
|
|
@themes = splice( @themes, $i_first, $opts{show} );
|
||
|
|
}
|
||
|
|
|
||
|
|
my @theme_data = ();
|
||
|
|
for my $theme (@themes) {
|
||
|
|
my $current_theme = ( $theme->themeid && ( $theme->themeid == $current->themeid ) )
|
||
|
|
|| ( ( $theme->layoutid == $current->layoutid )
|
||
|
|
&& !$theme->themeid
|
||
|
|
&& !$current->themeid ) ? 1 : 0;
|
||
|
|
my $no_layer_edit = LJ::Hooks::run_hook( "no_theme_or_layer_edit", $u );
|
||
|
|
|
||
|
|
push @theme_data, get_theme_data( $theme, $current_theme, $no_layer_edit );
|
||
|
|
|
||
|
|
}
|
||
|
|
|
||
|
|
my $vars = {
|
||
|
|
cat_title => $cat_title,
|
||
|
|
max_page => $max_page,
|
||
|
|
themes => \@theme_data,
|
||
|
|
qargs => \%opts
|
||
|
|
};
|
||
|
|
|
||
|
|
return DW::Template->template_string( 'widget/themechooser.tt', $vars );
|
||
|
|
}
|
||
|
|
|
||
|
|
sub get_theme_data {
|
||
|
|
my ( $theme, $current, $no_layer_edit ) = @_;
|
||
|
|
my $tmp = {
|
||
|
|
imgurl => $theme->preview_imgurl,
|
||
|
|
layoutid => $theme->layoutid,
|
||
|
|
themeid => $theme->themeid,
|
||
|
|
name => $theme->{'name'},
|
||
|
|
designer => $theme->designer,
|
||
|
|
layout => $theme->{'layout_name'},
|
||
|
|
};
|
||
|
|
|
||
|
|
$tmp->{'designer_link'} = LJ::create_url(
|
||
|
|
"/customize",
|
||
|
|
keep_args => [ 'show', 'authas' ],
|
||
|
|
args => { designer => $theme->designer }
|
||
|
|
) if $theme->designer;
|
||
|
|
$tmp->{'layout_link'} = LJ::create_url(
|
||
|
|
"/customize",
|
||
|
|
keep_args => [ 'show', 'authas' ],
|
||
|
|
args => { layoutid => $theme->layoutid }
|
||
|
|
);
|
||
|
|
$tmp->{'current'} = $current;
|
||
|
|
|
||
|
|
if ( $current && !$no_layer_edit && $theme->is_custom ) {
|
||
|
|
$tmp->{can_edit_layout} = $theme->layoutid && !$theme->{layout_uniq} ? 1 : 0;
|
||
|
|
$tmp->{can_edit_theme} = $theme->themeid && !$theme->{uniq} ? 1 : 0;
|
||
|
|
}
|
||
|
|
|
||
|
|
if ( $theme->themeid ) {
|
||
|
|
$tmp->{preview_url} = LJ::create_url( "/customize/preview_redirect",
|
||
|
|
args => { 'themeid' => $theme->themeid } );
|
||
|
|
}
|
||
|
|
else {
|
||
|
|
$tmp->{preview_url} = LJ::create_url( "/customize/preview_redirect",
|
||
|
|
args => { 'layoutid' => $theme->layoutid } );
|
||
|
|
}
|
||
|
|
return $tmp;
|
||
|
|
}
|
||
|
|
|
||
|
|
sub handle_post {
|
||
|
|
my $class = shift;
|
||
|
|
my $post = shift;
|
||
|
|
my %opts = @_;
|
||
|
|
|
||
|
|
my $u = $class->get_effective_remote();
|
||
|
|
die "Invalid user." unless LJ::isu($u);
|
||
|
|
|
||
|
|
my $themeid = $post->{apply_themeid} + 0;
|
||
|
|
my $layoutid = $post->{apply_layoutid} + 0;
|
||
|
|
|
||
|
|
# we need to load sponsor's themes for sponsored users
|
||
|
|
my $substitue_user = LJ::Hooks::run_hook( "substitute_s2_layers_user", $u );
|
||
|
|
my $effective_u = defined $substitue_user ? $substitue_user : $u;
|
||
|
|
my $theme;
|
||
|
|
if ($themeid) {
|
||
|
|
$theme = LJ::S2Theme->load_by_themeid( $themeid, $effective_u );
|
||
|
|
}
|
||
|
|
elsif ($layoutid) {
|
||
|
|
$theme = LJ::S2Theme->load_custom_layoutid( $layoutid, $effective_u );
|
||
|
|
}
|
||
|
|
else {
|
||
|
|
die "No theme id or layout id specified.";
|
||
|
|
}
|
||
|
|
|
||
|
|
LJ::Customize->apply_theme( $u, $theme );
|
||
|
|
LJ::Hooks::run_hooks( 'apply_theme', $u );
|
||
|
|
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
|
||
|
|
sub js {
|
||
|
|
q [
|
||
|
|
initWidget: function () {
|
||
|
|
var self = this;
|
||
|
|
|
||
|
|
var filter_links = DOM.getElementsByClassName(document, "theme-cat");
|
||
|
|
filter_links = filter_links.concat(DOM.getElementsByClassName(document, "theme-layout"));
|
||
|
|
filter_links = filter_links.concat(DOM.getElementsByClassName(document, "theme-designer"));
|
||
|
|
filter_links = filter_links.concat(DOM.getElementsByClassName(document, "theme-page"));
|
||
|
|
page_links = document.querySelectorAll(".pagination a");
|
||
|
|
page_links.forEach(link => {
|
||
|
|
filter_links.push(link);
|
||
|
|
})
|
||
|
|
|
||
|
|
// add event listeners to all of the category, layout, designer, and page links
|
||
|
|
// adding an event listener to page is done separately because we need to be sure to use that if it is there,
|
||
|
|
// and we will miss it if it is there but there was another arg before it in the URL
|
||
|
|
filter_links.forEach(function (filter_link) {
|
||
|
|
console.log(filter_link);
|
||
|
|
var getArgs = LiveJournal.parseGetArgs(filter_link.href);
|
||
|
|
if (getArgs["page"]) {
|
||
|
|
DOM.addEventListener(filter_link, "click", function (evt) { Customize.ThemeNav.filterThemes(evt, "page", getArgs["page"]) });
|
||
|
|
} else {
|
||
|
|
for (var arg in getArgs) {
|
||
|
|
if (!getArgs.hasOwnProperty(arg)) continue;
|
||
|
|
if (arg == "authas" || arg == "show") continue;
|
||
|
|
DOM.addEventListener(filter_link, "click", function (evt) { Customize.ThemeNav.filterThemes(evt, arg, getArgs[arg]) });
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
});
|
||
|
|
|
||
|
|
// add event listeners to all of the apply theme forms
|
||
|
|
var apply_forms = DOM.getElementsByClassName(document, "theme-form");
|
||
|
|
apply_forms.forEach(function (form) {
|
||
|
|
DOM.addEventListener(form, "submit", function (evt) { self.applyTheme(evt, form) });
|
||
|
|
});
|
||
|
|
|
||
|
|
// add event listeners to the preview links
|
||
|
|
var preview_links = DOM.getElementsByClassName(document, "theme-preview-link");
|
||
|
|
preview_links.forEach(function (preview_link) {
|
||
|
|
DOM.addEventListener(preview_link, "click", function (evt) { self.previewTheme(evt, preview_link.href) });
|
||
|
|
});
|
||
|
|
|
||
|
|
// add event listener to the page and show dropdowns
|
||
|
|
//DOM.addEventListener($('.pagination a'), "click", function (evt) { Customize.ThemeNav.filterThemes(evt, "page", $('page_dropdown_top').value) });
|
||
|
|
// DOM.addEventListener($('page_dropdown_bottom'), "change", function (evt) { Customize.ThemeNav.filterThemes(evt, "page", $('page_dropdown_bottom').value) });
|
||
|
|
DOM.addEventListener($('show_dropdown_top'), "change", function (evt) { Customize.ThemeNav.filterThemes(evt, "show", $('show_dropdown_top').value) });
|
||
|
|
DOM.addEventListener($('show_dropdown_bottom'), "change", function (evt) { Customize.ThemeNav.filterThemes(evt, "show", $('show_dropdown_bottom').value) });
|
||
|
|
},
|
||
|
|
applyTheme: function (evt, form) {
|
||
|
|
var given_themeid = form["Widget[ThemeChooser]_apply_themeid"].value + "";
|
||
|
|
var given_layoutid = form["Widget[ThemeChooser]_apply_layoutid"].value + "";
|
||
|
|
$("theme_btn_" + given_layoutid + given_themeid).disabled = true;
|
||
|
|
DOM.addClassName($("theme_btn_" + given_layoutid + given_themeid), "theme-button-disabled disabled");
|
||
|
|
|
||
|
|
this.doPost({
|
||
|
|
apply_themeid: given_themeid,
|
||
|
|
apply_layoutid: given_layoutid
|
||
|
|
});
|
||
|
|
|
||
|
|
Event.stop(evt);
|
||
|
|
},
|
||
|
|
onData: function (data) {
|
||
|
|
Customize.ThemeNav.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
|
||
|
|
});
|
||
|
|
alert(Customize.ThemeChooser.confirmation);
|
||
|
|
LiveJournal.run_hook("update_other_widgets", "ThemeChooser");
|
||
|
|
},
|
||
|
|
previewTheme: function (evt, href) {
|
||
|
|
window.open(href, 'theme_preview', 'resizable=yes,status=yes,toolbar=no,location=no,menubar=no,scrollbars=yes');
|
||
|
|
Event.stop(evt);
|
||
|
|
},
|
||
|
|
onRefresh: function (data) {
|
||
|
|
this.initWidget();
|
||
|
|
}
|
||
|
|
];
|
||
|
|
}
|
||
|
|
|
||
|
|
1;
|