[dw-free] move cgi-bin/lj*.pl files into proper modules (in cgi-bin/LJ)
[commit: http://hg.dwscoalition.org/dw-free/rev/54cc18fd5a38]
http://bugs.dwscoalition.org/show_bug.cgi?id=1726
htmlcontrols.pl => LJ/HTMLControls.pm (no package changes)
Patch by
kareila.
Files modified:
http://bugs.dwscoalition.org/show_bug.cgi?id=1726
htmlcontrols.pl => LJ/HTMLControls.pm (no package changes)
Patch by
![[personal profile]](https://www.dreamwidth.org/img/silk/identity/user.png)
Files modified:
- cgi-bin/LJ/Comment.pm
- cgi-bin/LJ/HTMLControls.pm
- cgi-bin/htmlcontrols.pl
- cgi-bin/modperl_subs.pl
- t/settings.t
- t/talklib-mail-migrate.t
-------------------------------------------------------------------------------- diff -r b9043502017a -r 54cc18fd5a38 cgi-bin/LJ/Comment.pm --- a/cgi-bin/LJ/Comment.pm Mon Nov 07 18:28:01 2011 +0800 +++ b/cgi-bin/LJ/Comment.pm Mon Nov 07 18:31:09 2011 +0800 @@ -20,11 +20,9 @@ use strict; use Carp qw/ croak /; + use LJ::Entry; - -use lib "$LJ::HOME/cgi-bin"; - -require "htmlcontrols.pl"; +use LJ::HTMLControls; use LJ::Talk; =head1 NAME diff -r b9043502017a -r 54cc18fd5a38 cgi-bin/LJ/HTMLControls.pm --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/cgi-bin/LJ/HTMLControls.pm Mon Nov 07 18:31:09 2011 +0800 @@ -0,0 +1,503 @@ +#!/usr/bin/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; + +use strict; + +# <LJFUNC> +# name: LJ::html_datetime +# class: component +# des: Creates date and time control HTML form elements. +# info: Parse output later with [func[LJ::html_datetime_decode]]. +# args: +# des-: +# returns: +# </LJFUNC> +sub html_datetime +{ + my $opts = shift; + my $lang = $opts->{'lang'} || "EN"; + my ($yyyy, $mm, $dd, $hh, $nn, $ss); + my $ret; + my $name = $opts->{name} || ''; + my $id = $opts->{id} || ''; + my $disabled = $opts->{'disabled'} ? 1 : 0; + + my %extra_opts; + foreach (grep { ! /^(name|id|disabled|seconds|notime|lang|default)$/ } keys %$opts) { + $extra_opts{$_} = $opts->{$_}; + } + + if ($opts->{'default'} =~ /^(\d\d\d\d)-(\d\d)-(\d\d)(?: (\d\d):(\d\d):(\d\d))?/) { + ( $yyyy, $mm, $dd, $hh, $nn, $ss ) = ( $1 > 0 ? $1 : "", + $2+0, + $3 > 0 ? $3+0 : "", + defined $4 && $4 > 0 ? $4 : "", + defined $5 && $5 > 0 ? $5 : "", + defined $6 && $6 > 0 ? $6 : "" ); + } + $ret .= html_select( { name => "${name}_mm", + id => "${id}_mm", + selected => $mm, + class => 'select', + title => 'month', + disabled => $disabled, %extra_opts, + }, + map { $_, LJ::Lang::month_long_ml($_) } (1..12) ); + $ret .= html_text( { name => "${name}_dd", + id => "${id}_dd", + size => '2', + class => 'text', + maxlength => '2', + value => $dd, + title => 'day', + disabled => $disabled, %extra_opts, + } ); + $ret .= html_text( { name => "${name}_yyyy", + id => "${id}_yyyy", + size => '4', + class => 'text', + maxlength => '4', + value => $yyyy, + title => 'year', + disabled => $disabled, %extra_opts, + } ); + unless ( $opts->{notime} ) { + $ret .= ' '; + $ret .= html_text( { name => "${name}_hh", + id => "${id}_hh", + size => '2', + maxlength => '2', + value => $hh, + title => 'hour', + disabled => $disabled, + } ) . ':'; + $ret .= html_text( { name => "${name}_nn", + id => "${id}_nn", + size => '2', + maxlength => '2', + value => $nn, + title => 'minutes', + disabled => $disabled, + } ); + if ( $opts->{seconds} ) { + $ret .= ':'; + $ret .= html_text( { name => "${name}_ss", + id => "${id}_ss", + size => '2', + maxlength => '2', + value => $ss, + title => 'seconds', + disabled => $disabled, + } ); + } + } + + return $ret; +} + +# <LJFUNC> +# name: LJ::html_datetime_decode +# class: component +# des: Parses output of HTML form controls generated by [func[LJ::html_datetime]]. +# info: +# args: +# des-: +# returns: +# </LJFUNC> +sub html_datetime_decode +{ + my $opts = shift; + my $hash = shift; + my $name = $opts->{name} || ''; + return sprintf("%04d-%02d-%02d %02d:%02d:%02d", + $hash->{"${name}_yyyy"} || 0, + $hash->{"${name}_mm"} || 0, + $hash->{"${name}_dd"} || 0, + $hash->{"${name}_hh"} || 0, + $hash->{"${name}_nn"} || 0, + $hash->{"${name}_ss"} || 0 ); +} + +# <LJFUNC> +# name: LJ::html_select +# class: component +# des: Creates a drop-down box or listbox HTML form element (the <select> tag). +# info: +# args: opts +# A hashref with an attribute of optgroup will be treated as a list of of value => text pairs within an optgroup +# des-opts: A hashref of options. Special options are: +# 'raw' - inserts value unescaped into select tag; +# 'noescape' - won't escape key values if set to 1; +# 'disabled' - disables the element; +# 'include_ids' - bool. If true, puts id attributes on each element in the drop-down. +# ids are off by default, to reduce page sizes with large drop-down menus; +# 'multiple' - creates a drop-down if 0, a multi-select listbox if 1; +# 'selected' - if multiple, an arrayref of selected values; otherwise, +# a scalar equalling the selected value; +# All other options will be treated as HTML attribute/value pairs. +# returns: The generated HTML. +# </LJFUNC> +sub html_select +{ + my $opts = shift; + my @items = @_; + my $ehtml = $opts->{'noescape'} ? 0 : 1; + my $ret; + $ret .= "<select"; + $ret .= " $opts->{'raw'}" if $opts->{'raw'}; + $ret .= " disabled='disabled'" if $opts->{'disabled'}; + $ret .= " multiple='multiple'" if $opts->{'multiple'}; + foreach (grep { ! /^(raw|disabled|selected|noescape|multiple)$/ } keys %$opts) { + my $opt = $opts->{$_} || ''; + $ret .= " $_=\"" . ( $ehtml ? ehtml( $opt ) : $opt ) . "\""; + } + $ret .= ">\n"; + + # build hashref from arrayref if multiple selected + my $selref; + $selref = { map { $_, 1 } @{$opts->{'selected'}} } + if $opts->{'multiple'} && ref $opts->{'selected'} eq 'ARRAY'; + + my $did_sel = 0; + while (defined (my $value = shift @items)) { + + # items can be either pairs of $value, $text or a list of $it hashrefs (or a mix) + my $it = {}; + my $text; + if (ref $value) { + $it = $value; + $value = $it->{value}; + $text = $it->{text}; + } else { + $text = shift @items; + } + + if ( $it->{optgroup} ) { + $ret .= "<optgroup label='$it->{optgroup}'>"; + $ret .= LJ::_html_option( $_->{value}, $_->{text}, {}, $opts, $ehtml, $selref, \$did_sel ) + foreach @{$it->{items} || []}; + $ret .= "</optgroup>"; + } else { + $ret .= LJ::_html_option( $value, $text, $it, $opts, $ehtml, + $selref, \$did_sel ); + } + } + $ret .= "</select>"; + return $ret; +} + +sub _html_option { + my ( $value, $text, $item, $opts, $ehtml, $selref, $did_sel ) = @_; + + my $sel = ""; + # multiple-mode or single-mode? + if ( $selref && ( ref $selref eq 'HASH' ) && $selref->{$value} || + $opts->{selected} && ( $opts->{selected} eq $value ) && ! $$did_sel++ ) { + + $sel = " selected='selected'"; + } + $value = $ehtml ? ehtml( $value ) : $value; + + my $id = ''; + if ( $opts->{include_ids} && $opts->{name} ne "" && $value ne "" ) { + $id = " id='$opts->{'name'}_$value'"; + } + + # is this individual option disabled? + my $dis = $item->{disabled} ? " disabled='disabled' style='color: #999;'" : ''; + + return "<option value=\"$value\"$id$sel$dis>" . + ( $ehtml ? ehtml( $text ) : $text ) . "</option>\n"; +} + +# <LJFUNC> +# name: LJ::html_check +# class: component +# des: Creates HTML checkbox button, and radio button controls. +# info: Labels for checkboxes are through LJ::labelfy. +# It does this safely, by not including any HTML elements in the label tag. +# args: type, opts +# des-type: Valid types are 'radio' or 'checkbox'. +# des-opts: A hashref of options. Special options are: +# 'disabled' - disables the element; +# 'selected' - if multiple, an arrayref of selected values; otherwise, +# a scalar equalling the selected value; +# 'raw' - inserts value unescaped into select tag; +# 'noescape' - won't escape key values if set to 1; +# 'label' - label for checkbox; +# returns: +# </LJFUNC> +sub html_check +{ + my $opts = shift; + + my $disabled = $opts->{'disabled'} ? " disabled='disabled'" : ""; + my $ehtml = $opts->{'noescape'} ? 0 : 1; + my $ret; + if ( $opts->{type} && $opts->{type} eq "radio" ) { + $ret .= "<input type='radio'"; + } else { + $ret .= "<input type='checkbox'"; + } + if ($opts->{'selected'}) { $ret .= " checked='checked'"; } + if ($opts->{'raw'}) { $ret .= " $opts->{'raw'}"; } + foreach (grep { ! /^(disabled|type|selected|raw|noescape|label)$/ } keys %$opts) { + $ret .= " $_=\"" . ($ehtml ? ehtml($opts->{$_}) : $opts->{$_}) . "\""; + } + $ret .= "$disabled />"; + my $e_label = ($ehtml ? ehtml($opts->{'label'}) : $opts->{'label'}); + $e_label = LJ::labelfy($opts->{id}, $e_label); + $ret .= $e_label if $opts->{'label'}; + return $ret; +} + +# given a string and an id, return the string +# in a label, respecting HTML +sub labelfy { + my ($id, $text, $class) = @_; + $id = '' unless defined $id; + $text = '' unless defined $text; + + $class = LJ::ehtml( $class || "" ); + $class = qq{class="$class"} if $class; + + $text =~ s! + ^([^<]+) + ! + <label for="$id" $class> + $1 + </label> + !x; + + return $text; +} + +# <LJFUNC> +# name: LJ::html_text +# class: component +# des: Creates a text input field, for single-line input. +# info: Allows 'type' => 'password' flag. +# args: +# des-: +# returns: The generated HTML. +# </LJFUNC> +sub html_text +{ + my $opts = shift; + + my $disabled = $opts->{'disabled'} ? " disabled='disabled'" : ""; + my $ehtml = $opts->{'noescape'} ? 0 : 1; + my $type = 'text'; + $type = $opts->{type} if $opts->{type} && + ( $opts->{type} eq 'password' || + $opts->{type} eq 'search' ); + my $ret = ''; + $ret .= "<input type=\"$type\""; + foreach (grep { ! /^(type|disabled|raw|noescape)$/ } keys %$opts) { + my $val = defined $opts->{$_} ? $opts->{$_} : ''; + $ret .= " $_=\"" . ( $ehtml ? LJ::ehtml( $val ) : $val ) . "\""; + } + if ($opts->{'raw'}) { $ret .= " $opts->{'raw'}"; } + $ret .= "$disabled />"; + return $ret; +} + +# <LJFUNC> +# name: LJ::html_textarea +# class: component +# des: Creates a text box for multi-line input (the <textarea> tag). +# info: +# args: +# des-: +# returns: The generated HTML. +# </LJFUNC> +sub html_textarea +{ + my $opts = $_[0]; + + my $disabled = $opts->{disabled} ? " disabled='disabled'" : ""; + my $ehtml = $opts->{noescape} ? 0 : 1; + my $value = $opts->{value} || ''; + $value = ehtml( $value ) if $ehtml; + + my $ret = "<textarea"; + foreach (grep { ! /^(disabled|raw|value|noescape)$/ } keys %$opts) { + $ret .= " $_=\"" . ($ehtml ? ehtml($opts->{$_}) : $opts->{$_}) . "\""; + } + $ret .= " $opts->{raw}" if $opts->{raw}; + $ret .= "$disabled>$value</textarea>"; + return $ret; +} + +# <LJFUNC> +# name: LJ::html_color +# class: component +# des: A text field with attached color preview and button to choose a color. +# info: Depends on the client-side Color Picker. +# args: opts +# des-opts: Valid options are: 'onchange' argument, which happens when +# color picker button is clicked, or when focus is changed to text box; +# 'disabled'; and 'raw' , for unescaped input. +# returns: +# </LJFUNC> +sub html_color +{ + my $opts = shift; + + my $htmlname = ehtml($opts->{'name'}); + my $des = ehtml($opts->{'des'}) || "Pick a Color"; + my $ret; + + ## Output the preview box and picker button with script so that + ## they don't appear when JavaScript is unavailable. + $ret .= "<script language=\"JavaScript\"><!--\n". + "document.write('<span style=\"border: 1px solid #000000; ". + "padding-left: 2em; background-color: " . ehtml($opts->{'default'} || "") . ";\" ". + "id=\"${htmlname}_disp\""; + if ($opts->{no_btn}) { + $ret .= " onclick=\"spawnPicker(findel(\\'${htmlname}\\')," . + "findel(\\'${htmlname}_disp\\'),\\'$des\\'); " . + LJ::ejs($opts->{'onchange'}) . + " return false;\""; + } + $ret .= "> </span>'); ". + "\n--></script>\n"; + + # 'onchange' argument happens when color picker button is clicked, + # or when focus is changed to text box + + $ret .= html_text({ 'size' => 8, 'maxlength' => 7, 'name' => $htmlname, 'id' => $htmlname, + 'onchange' => "setBGColorWithId(findel('${htmlname}_disp'),'${htmlname}');", + 'onfocus' => $opts->{'onchange'}, + 'disabled' => $opts->{'disabled'}, 'value' => $opts->{'default'}, + 'noescape' => 1, 'raw' => $opts->{'raw'}, + }); + + unless ($opts->{no_btn}) { + my $disabled = $opts->{'disabled'} ? "disabled=\'disabled\'" : ''; + $ret .= "<script language=\"JavaScript\"><!--\n". + "document.write('<button ". + "onclick=\"spawnPicker(findel(\\'${htmlname}\\')," . + "findel(\\'${htmlname}_disp\\'),\\'$des\\'); " . + LJ::ejs($opts->{'onchange'}) . + " return false;\"$disabled>Choose...</button>'); ". + "\n--></script>\n"; + } + + # A little help for the non-JavaScript folks + $ret .= "<noscript> (#<var>rr</var><var>gg</var><var>bb</var>)</noscript>"; + + return $ret; +} + +# <LJFUNC> +# name: LJ::html_hidden +# class: component +# des: Makes the HTML for a hidden form element. +# args: name, val, opts +# des-name: Name of form element (will be HTML escaped). +# des-val: Value of form element (will be HTML escaped). +# des-opts: Can optionally take arguments that are hashrefs +# and extract name/value/other standard keys from that. Can also be +# mixed with the older style key/value array calling format. +# returns: HTML +# </LJFUNC> +sub html_hidden +{ + my $ret; + + while (@_) { + my $name = shift; + my $val; + my $ehtml = 1; + my $extra = ''; + if (ref $name eq 'HASH') { + my $opts = $name; + + $val = $opts->{value}; + $name = $opts->{name}; + + $ehtml = $opts->{'noescape'} ? 0 : 1; + foreach (grep { ! /^(name|value|raw|noescape)$/ } keys %$opts) { + $extra .= " $_=\"" . ($ehtml ? ehtml($opts->{$_}) : $opts->{$_}) . "\""; + } + + $extra .= " $opts->{'raw'}" if $opts->{'raw'}; + + } else { + $val = shift; + } + + $ret .= "<input type='hidden'"; + # allow override of these in 'raw' + $ret .= " name=\"" . ($ehtml ? ehtml($name) : $name) . "\"" if $name; + $ret .= " value=\"" . ($ehtml ? ehtml($val) : $val) . "\"" if defined $val; + $ret .= "$extra />"; + } + return $ret; +} + +# <LJFUNC> +# name: LJ::html_submit +# class: component +# des: Makes the HTML for a submit button. +# info: If only one argument is given it is +# assumed LJ::html_submit(undef, 'value') was meant. +# args: name, val, opts?, type +# des-name: Name of form element (will be HTML escaped). +# des-val: Value of form element, and label of button (will be HTML escaped). +# des-opts: Optional hashref of additional tag attributes. +# A hashref of options. Special options are: +# 'raw' - inserts value unescaped into select tag; +# 'disabled' - disables the element; +# 'noescape' - won't escape key values if set to 1; +# des-type: Optional. Value format is type => (submit|reset). Defaults to submit. +# returns: HTML +# </LJFUNC> +sub html_submit +{ + my ($name, $val, $opts) = @_; + + # if one argument, assume (undef, $val) + if (@_ == 1) { + $val = $name; + $name = undef; + } + + my ( $eopts, $disabled, $raw ) = ( '','','' ); + my $type = 'submit'; + + my $ehtml; + if ($opts && ref $opts eq 'HASH') { + $disabled = " disabled='disabled'" if $opts->{'disabled'}; + $raw = " $opts->{'raw'}" if $opts->{'raw'}; + $type = 'reset' if $opts->{type} && $opts->{type} eq 'reset'; + + $ehtml = $opts->{'noescape'} ? 0 : 1; + foreach (grep { ! /^(raw|disabled|noescape|type)$/ } keys %$opts) { + $eopts .= " $_=\"" . ($ehtml ? ehtml($opts->{$_}) : $opts->{$_}) . "\""; + } + } + my $ret = "<input type='$type'"; + # allow override of these in 'raw' + $ret .= " name=\"" . ($ehtml ? ehtml($name) : $name) . "\"" if $name; + $ret .= " value=\"" . ($ehtml ? ehtml($val) : $val) . "\"" if defined $val; + $ret .= "$eopts$raw$disabled />"; + return $ret; +} + +1; diff -r b9043502017a -r 54cc18fd5a38 cgi-bin/htmlcontrols.pl --- a/cgi-bin/htmlcontrols.pl Mon Nov 07 18:28:01 2011 +0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,503 +0,0 @@ -#!/usr/bin/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; - -use strict; - -# <LJFUNC> -# name: LJ::html_datetime -# class: component -# des: Creates date and time control HTML form elements. -# info: Parse output later with [func[LJ::html_datetime_decode]]. -# args: -# des-: -# returns: -# </LJFUNC> -sub html_datetime -{ - my $opts = shift; - my $lang = $opts->{'lang'} || "EN"; - my ($yyyy, $mm, $dd, $hh, $nn, $ss); - my $ret; - my $name = $opts->{name} || ''; - my $id = $opts->{id} || ''; - my $disabled = $opts->{'disabled'} ? 1 : 0; - - my %extra_opts; - foreach (grep { ! /^(name|id|disabled|seconds|notime|lang|default)$/ } keys %$opts) { - $extra_opts{$_} = $opts->{$_}; - } - - if ($opts->{'default'} =~ /^(\d\d\d\d)-(\d\d)-(\d\d)(?: (\d\d):(\d\d):(\d\d))?/) { - ( $yyyy, $mm, $dd, $hh, $nn, $ss ) = ( $1 > 0 ? $1 : "", - $2+0, - $3 > 0 ? $3+0 : "", - defined $4 && $4 > 0 ? $4 : "", - defined $5 && $5 > 0 ? $5 : "", - defined $6 && $6 > 0 ? $6 : "" ); - } - $ret .= html_select( { name => "${name}_mm", - id => "${id}_mm", - selected => $mm, - class => 'select', - title => 'month', - disabled => $disabled, %extra_opts, - }, - map { $_, LJ::Lang::month_long_ml($_) } (1..12) ); - $ret .= html_text( { name => "${name}_dd", - id => "${id}_dd", - size => '2', - class => 'text', - maxlength => '2', - value => $dd, - title => 'day', - disabled => $disabled, %extra_opts, - } ); - $ret .= html_text( { name => "${name}_yyyy", - id => "${id}_yyyy", - size => '4', - class => 'text', - maxlength => '4', - value => $yyyy, - title => 'year', - disabled => $disabled, %extra_opts, - } ); - unless ( $opts->{notime} ) { - $ret .= ' '; - $ret .= html_text( { name => "${name}_hh", - id => "${id}_hh", - size => '2', - maxlength => '2', - value => $hh, - title => 'hour', - disabled => $disabled, - } ) . ':'; - $ret .= html_text( { name => "${name}_nn", - id => "${id}_nn", - size => '2', - maxlength => '2', - value => $nn, - title => 'minutes', - disabled => $disabled, - } ); - if ( $opts->{seconds} ) { - $ret .= ':'; - $ret .= html_text( { name => "${name}_ss", - id => "${id}_ss", - size => '2', - maxlength => '2', - value => $ss, - title => 'seconds', - disabled => $disabled, - } ); - } - } - - return $ret; -} - -# <LJFUNC> -# name: LJ::html_datetime_decode -# class: component -# des: Parses output of HTML form controls generated by [func[LJ::html_datetime]]. -# info: -# args: -# des-: -# returns: -# </LJFUNC> -sub html_datetime_decode -{ - my $opts = shift; - my $hash = shift; - my $name = $opts->{name} || ''; - return sprintf("%04d-%02d-%02d %02d:%02d:%02d", - $hash->{"${name}_yyyy"} || 0, - $hash->{"${name}_mm"} || 0, - $hash->{"${name}_dd"} || 0, - $hash->{"${name}_hh"} || 0, - $hash->{"${name}_nn"} || 0, - $hash->{"${name}_ss"} || 0 ); -} - -# <LJFUNC> -# name: LJ::html_select -# class: component -# des: Creates a drop-down box or listbox HTML form element (the <select> tag). -# info: -# args: opts -# A hashref with an attribute of optgroup will be treated as a list of of value => text pairs within an optgroup -# des-opts: A hashref of options. Special options are: -# 'raw' - inserts value unescaped into select tag; -# 'noescape' - won't escape key values if set to 1; -# 'disabled' - disables the element; -# 'include_ids' - bool. If true, puts id attributes on each element in the drop-down. -# ids are off by default, to reduce page sizes with large drop-down menus; -# 'multiple' - creates a drop-down if 0, a multi-select listbox if 1; -# 'selected' - if multiple, an arrayref of selected values; otherwise, -# a scalar equalling the selected value; -# All other options will be treated as HTML attribute/value pairs. -# returns: The generated HTML. -# </LJFUNC> -sub html_select -{ - my $opts = shift; - my @items = @_; - my $ehtml = $opts->{'noescape'} ? 0 : 1; - my $ret; - $ret .= "<select"; - $ret .= " $opts->{'raw'}" if $opts->{'raw'}; - $ret .= " disabled='disabled'" if $opts->{'disabled'}; - $ret .= " multiple='multiple'" if $opts->{'multiple'}; - foreach (grep { ! /^(raw|disabled|selected|noescape|multiple)$/ } keys %$opts) { - my $opt = $opts->{$_} || ''; - $ret .= " $_=\"" . ( $ehtml ? ehtml( $opt ) : $opt ) . "\""; - } - $ret .= ">\n"; - - # build hashref from arrayref if multiple selected - my $selref; - $selref = { map { $_, 1 } @{$opts->{'selected'}} } - if $opts->{'multiple'} && ref $opts->{'selected'} eq 'ARRAY'; - - my $did_sel = 0; - while (defined (my $value = shift @items)) { - - # items can be either pairs of $value, $text or a list of $it hashrefs (or a mix) - my $it = {}; - my $text; - if (ref $value) { - $it = $value; - $value = $it->{value}; - $text = $it->{text}; - } else { - $text = shift @items; - } - - if ( $it->{optgroup} ) { - $ret .= "<optgroup label='$it->{optgroup}'>"; - $ret .= LJ::_html_option( $_->{value}, $_->{text}, {}, $opts, $ehtml, $selref, \$did_sel ) - foreach @{$it->{items} || []}; - $ret .= "</optgroup>"; - } else { - $ret .= LJ::_html_option( $value, $text, $it, $opts, $ehtml, - $selref, \$did_sel ); - } - } - $ret .= "</select>"; - return $ret; -} - -sub _html_option { - my ( $value, $text, $item, $opts, $ehtml, $selref, $did_sel ) = @_; - - my $sel = ""; - # multiple-mode or single-mode? - if ( $selref && ( ref $selref eq 'HASH' ) && $selref->{$value} || - $opts->{selected} && ( $opts->{selected} eq $value ) && ! $$did_sel++ ) { - - $sel = " selected='selected'"; - } - $value = $ehtml ? ehtml( $value ) : $value; - - my $id = ''; - if ( $opts->{include_ids} && $opts->{name} ne "" && $value ne "" ) { - $id = " id='$opts->{'name'}_$value'"; - } - - # is this individual option disabled? - my $dis = $item->{disabled} ? " disabled='disabled' style='color: #999;'" : ''; - - return "<option value=\"$value\"$id$sel$dis>" . - ( $ehtml ? ehtml( $text ) : $text ) . "</option>\n"; -} - -# <LJFUNC> -# name: LJ::html_check -# class: component -# des: Creates HTML checkbox button, and radio button controls. -# info: Labels for checkboxes are through LJ::labelfy. -# It does this safely, by not including any HTML elements in the label tag. -# args: type, opts -# des-type: Valid types are 'radio' or 'checkbox'. -# des-opts: A hashref of options. Special options are: -# 'disabled' - disables the element; -# 'selected' - if multiple, an arrayref of selected values; otherwise, -# a scalar equalling the selected value; -# 'raw' - inserts value unescaped into select tag; -# 'noescape' - won't escape key values if set to 1; -# 'label' - label for checkbox; -# returns: -# </LJFUNC> -sub html_check -{ - my $opts = shift; - - my $disabled = $opts->{'disabled'} ? " disabled='disabled'" : ""; - my $ehtml = $opts->{'noescape'} ? 0 : 1; - my $ret; - if ( $opts->{type} && $opts->{type} eq "radio" ) { - $ret .= "<input type='radio'"; - } else { - $ret .= "<input type='checkbox'"; - } - if ($opts->{'selected'}) { $ret .= " checked='checked'"; } - if ($opts->{'raw'}) { $ret .= " $opts->{'raw'}"; } - foreach (grep { ! /^(disabled|type|selected|raw|noescape|label)$/ } keys %$opts) { - $ret .= " $_=\"" . ($ehtml ? ehtml($opts->{$_}) : $opts->{$_}) . "\""; - } - $ret .= "$disabled />"; - my $e_label = ($ehtml ? ehtml($opts->{'label'}) : $opts->{'label'}); - $e_label = LJ::labelfy($opts->{id}, $e_label); - $ret .= $e_label if $opts->{'label'}; - return $ret; -} - -# given a string and an id, return the string -# in a label, respecting HTML -sub labelfy { - my ($id, $text, $class) = @_; - $id = '' unless defined $id; - $text = '' unless defined $text; - - $class = LJ::ehtml( $class || "" ); - $class = qq{class="$class"} if $class; - - $text =~ s! - ^([^<]+) - ! - <label for="$id" $class> - $1 - </label> - !x; - - return $text; -} - -# <LJFUNC> -# name: LJ::html_text -# class: component -# des: Creates a text input field, for single-line input. -# info: Allows 'type' => 'password' flag. -# args: -# des-: -# returns: The generated HTML. -# </LJFUNC> -sub html_text -{ - my $opts = shift; - - my $disabled = $opts->{'disabled'} ? " disabled='disabled'" : ""; - my $ehtml = $opts->{'noescape'} ? 0 : 1; - my $type = 'text'; - $type = $opts->{type} if $opts->{type} && - ( $opts->{type} eq 'password' || - $opts->{type} eq 'search' ); - my $ret = ''; - $ret .= "<input type=\"$type\""; - foreach (grep { ! /^(type|disabled|raw|noescape)$/ } keys %$opts) { - my $val = defined $opts->{$_} ? $opts->{$_} : ''; - $ret .= " $_=\"" . ( $ehtml ? LJ::ehtml( $val ) : $val ) . "\""; - } - if ($opts->{'raw'}) { $ret .= " $opts->{'raw'}"; } - $ret .= "$disabled />"; - return $ret; -} - -# <LJFUNC> -# name: LJ::html_textarea -# class: component -# des: Creates a text box for multi-line input (the <textarea> tag). -# info: -# args: -# des-: -# returns: The generated HTML. -# </LJFUNC> -sub html_textarea -{ - my $opts = $_[0]; - - my $disabled = $opts->{disabled} ? " disabled='disabled'" : ""; - my $ehtml = $opts->{noescape} ? 0 : 1; - my $value = $opts->{value} || ''; - $value = ehtml( $value ) if $ehtml; - - my $ret = "<textarea"; - foreach (grep { ! /^(disabled|raw|value|noescape)$/ } keys %$opts) { - $ret .= " $_=\"" . ($ehtml ? ehtml($opts->{$_}) : $opts->{$_}) . "\""; - } - $ret .= " $opts->{raw}" if $opts->{raw}; - $ret .= "$disabled>$value</textarea>"; - return $ret; -} - -# <LJFUNC> -# name: LJ::html_color -# class: component -# des: A text field with attached color preview and button to choose a color. -# info: Depends on the client-side Color Picker. -# args: opts -# des-opts: Valid options are: 'onchange' argument, which happens when -# color picker button is clicked, or when focus is changed to text box; -# 'disabled'; and 'raw' , for unescaped input. -# returns: -# </LJFUNC> -sub html_color -{ - my $opts = shift; - - my $htmlname = ehtml($opts->{'name'}); - my $des = ehtml($opts->{'des'}) || "Pick a Color"; - my $ret; - - ## Output the preview box and picker button with script so that - ## they don't appear when JavaScript is unavailable. - $ret .= "<script language=\"JavaScript\"><!--\n". - "document.write('<span style=\"border: 1px solid #000000; ". - "padding-left: 2em; background-color: " . ehtml($opts->{'default'} || "") . ";\" ". - "id=\"${htmlname}_disp\""; - if ($opts->{no_btn}) { - $ret .= " onclick=\"spawnPicker(findel(\\'${htmlname}\\')," . - "findel(\\'${htmlname}_disp\\'),\\'$des\\'); " . - LJ::ejs($opts->{'onchange'}) . - " return false;\""; - } - $ret .= "> </span>'); ". - "\n--></script>\n"; - - # 'onchange' argument happens when color picker button is clicked, - # or when focus is changed to text box - - $ret .= html_text({ 'size' => 8, 'maxlength' => 7, 'name' => $htmlname, 'id' => $htmlname, - 'onchange' => "setBGColorWithId(findel('${htmlname}_disp'),'${htmlname}');", - 'onfocus' => $opts->{'onchange'}, - 'disabled' => $opts->{'disabled'}, 'value' => $opts->{'default'}, - 'noescape' => 1, 'raw' => $opts->{'raw'}, - }); - - unless ($opts->{no_btn}) { - my $disabled = $opts->{'disabled'} ? "disabled=\'disabled\'" : ''; - $ret .= "<script language=\"JavaScript\"><!--\n". - "document.write('<button ". - "onclick=\"spawnPicker(findel(\\'${htmlname}\\')," . - "findel(\\'${htmlname}_disp\\'),\\'$des\\'); " . - LJ::ejs($opts->{'onchange'}) . - " return false;\"$disabled>Choose...</button>'); ". - "\n--></script>\n"; - } - - # A little help for the non-JavaScript folks - $ret .= "<noscript> (#<var>rr</var><var>gg</var><var>bb</var>)</noscript>"; - - return $ret; -} - -# <LJFUNC> -# name: LJ::html_hidden -# class: component -# des: Makes the HTML for a hidden form element. -# args: name, val, opts -# des-name: Name of form element (will be HTML escaped). -# des-val: Value of form element (will be HTML escaped). -# des-opts: Can optionally take arguments that are hashrefs -# and extract name/value/other standard keys from that. Can also be -# mixed with the older style key/value array calling format. -# returns: HTML -# </LJFUNC> -sub html_hidden -{ - my $ret; - - while (@_) { - my $name = shift; - my $val; - my $ehtml = 1; - my $extra = ''; - if (ref $name eq 'HASH') { - my $opts = $name; - - $val = $opts->{value}; - $name = $opts->{name}; - - $ehtml = $opts->{'noescape'} ? 0 : 1; - foreach (grep { ! /^(name|value|raw|noescape)$/ } keys %$opts) { - $extra .= " $_=\"" . ($ehtml ? ehtml($opts->{$_}) : $opts->{$_}) . "\""; - } - - $extra .= " $opts->{'raw'}" if $opts->{'raw'}; - - } else { - $val = shift; - } - - $ret .= "<input type='hidden'"; - # allow override of these in 'raw' - $ret .= " name=\"" . ($ehtml ? ehtml($name) : $name) . "\"" if $name; - $ret .= " value=\"" . ($ehtml ? ehtml($val) : $val) . "\"" if defined $val; - $ret .= "$extra />"; - } - return $ret; -} - -# <LJFUNC> -# name: LJ::html_submit -# class: component -# des: Makes the HTML for a submit button. -# info: If only one argument is given it is -# assumed LJ::html_submit(undef, 'value') was meant. -# args: name, val, opts?, type -# des-name: Name of form element (will be HTML escaped). -# des-val: Value of form element, and label of button (will be HTML escaped). -# des-opts: Optional hashref of additional tag attributes. -# A hashref of options. Special options are: -# 'raw' - inserts value unescaped into select tag; -# 'disabled' - disables the element; -# 'noescape' - won't escape key values if set to 1; -# des-type: Optional. Value format is type => (submit|reset). Defaults to submit. -# returns: HTML -# </LJFUNC> -sub html_submit -{ - my ($name, $val, $opts) = @_; - - # if one argument, assume (undef, $val) - if (@_ == 1) { - $val = $name; - $name = undef; - } - - my ( $eopts, $disabled, $raw ) = ( '','','' ); - my $type = 'submit'; - - my $ehtml; - if ($opts && ref $opts eq 'HASH') { - $disabled = " disabled='disabled'" if $opts->{'disabled'}; - $raw = " $opts->{'raw'}" if $opts->{'raw'}; - $type = 'reset' if $opts->{type} && $opts->{type} eq 'reset'; - - $ehtml = $opts->{'noescape'} ? 0 : 1; - foreach (grep { ! /^(raw|disabled|noescape|type)$/ } keys %$opts) { - $eopts .= " $_=\"" . ($ehtml ? ehtml($opts->{$_}) : $opts->{$_}) . "\""; - } - } - my $ret = "<input type='$type'"; - # allow override of these in 'raw' - $ret .= " name=\"" . ($ehtml ? ehtml($name) : $name) . "\"" if $name; - $ret .= " value=\"" . ($ehtml ? ehtml($val) : $val) . "\"" if defined $val; - $ret .= "$eopts$raw$disabled />"; - return $ret; -} - -1; diff -r b9043502017a -r 54cc18fd5a38 cgi-bin/modperl_subs.pl --- a/cgi-bin/modperl_subs.pl Mon Nov 07 18:28:01 2011 +0800 +++ b/cgi-bin/modperl_subs.pl Mon Nov 07 18:31:09 2011 +0800 @@ -81,7 +81,7 @@ use LJ::Lang; use LJ::Links; use LJ::Syn; -require "htmlcontrols.pl"; +use LJ::HTMLControls; require "weblib.pl"; use LJ::Support; use LJ::CleanHTML; diff -r b9043502017a -r 54cc18fd5a38 t/settings.t --- a/t/settings.t Mon Nov 07 18:28:01 2011 +0800 +++ b/t/settings.t Mon Nov 07 18:31:09 2011 +0800 @@ -1,17 +1,14 @@ -# -*-perl-*- +#!/usr/bin/perl use strict; use Test::More; use lib "$ENV{LJHOME}/cgi-bin"; require 'ljlib.pl'; use LJ::Lang; +use LJ::HTMLControls; plan tests => 9; -package LJ; -require 'htmlcontrols.pl'; -package main; - use LJ::Setting::Gender; use LJ::Setting::Name; diff -r b9043502017a -r 54cc18fd5a38 t/talklib-mail-migrate.t --- a/t/talklib-mail-migrate.t Mon Nov 07 18:28:01 2011 +0800 +++ b/t/talklib-mail-migrate.t Mon Nov 07 18:31:09 2011 +0800 @@ -11,7 +11,7 @@ package LJ; require 'ljlib.pl'; -require 'htmlcontrols.pl'; +use LJ::HTMLControls; use LJ::Talk; use LJ::Test qw(temp_user memcache_stress); --------------------------------------------------------------------------------