svnno****@sourc*****
svnno****@sourc*****
2008年 4月 1日 (火) 12:35:14 JST
Revision: 560 http://svn.sourceforge.jp/cgi-bin/viewcvs.cgi?root=slashdotjp&view=rev&rev=560 Author: tach Date: 2008-04-01 12:35:14 +0900 (Tue, 01 Apr 2008) Log Message: ----------- merged from upstream T_2_5_0_198 Modified Paths: -------------- slashjp/branches/upstream/current/AUTHORS slashjp/branches/upstream/current/INSTALL slashjp/branches/upstream/current/Slash/DB/MySQL/MySQL.pm slashjp/branches/upstream/current/Slash/Hook/Hook.pm slashjp/branches/upstream/current/Slash/Slash.pm slashjp/branches/upstream/current/Slash/Utility/Comments/Comments.pm slashjp/branches/upstream/current/Slash/Utility/Environment/Environment.pm slashjp/branches/upstream/current/bin/install-slashsite slashjp/branches/upstream/current/docs/INSTALL.pod slashjp/branches/upstream/current/plugins/Admin/Admin.pm slashjp/branches/upstream/current/plugins/Admin/admin.pl slashjp/branches/upstream/current/plugins/Admin/templates/editStory;admin;default slashjp/branches/upstream/current/plugins/Admin/templates/signoff;misc;default slashjp/branches/upstream/current/plugins/Admin/templates/signoff_stats;misc;default slashjp/branches/upstream/current/plugins/Ajax/PLUGIN slashjp/branches/upstream/current/plugins/Ajax/htdocs/ajax.pl slashjp/branches/upstream/current/plugins/Ajax/htdocs/images/admin.js slashjp/branches/upstream/current/plugins/Ajax/htdocs/images/common.js slashjp/branches/upstream/current/plugins/Ajax/htdocs/images/nodnix.js slashjp/branches/upstream/current/plugins/Ajax/htdocs/images/sd_autocomplete.js slashjp/branches/upstream/current/plugins/Ajax/htdocs/images/sectionprefs.js slashjp/branches/upstream/current/plugins/Ajax/mysql_dump.sql slashjp/branches/upstream/current/plugins/Ajax/templates/edit_comment;ajax;default slashjp/branches/upstream/current/plugins/Ajax/templates/prefs_d2;ajax;default slashjp/branches/upstream/current/plugins/Email/templates/dispStory;email;default slashjp/branches/upstream/current/plugins/FAQSlashdot/faq/friends.shtml slashjp/branches/upstream/current/plugins/FireHose/FireHose.pm slashjp/branches/upstream/current/plugins/FireHose/PLUGIN slashjp/branches/upstream/current/plugins/FireHose/firehose.css slashjp/branches/upstream/current/plugins/FireHose/templates/firehose_tags_top;misc;default slashjp/branches/upstream/current/plugins/Messages/templates/dailyheadlines;messages;default slashjp/branches/upstream/current/plugins/Messages/templates/dailynews;messages;default slashjp/branches/upstream/current/plugins/Moderation/Moderation.pm slashjp/branches/upstream/current/plugins/Rating/Rating.pm slashjp/branches/upstream/current/plugins/ResKey/mysql_dump.sql slashjp/branches/upstream/current/plugins/Submit/submit.pl slashjp/branches/upstream/current/plugins/TagModeration/TagModeration.pm slashjp/branches/upstream/current/plugins/Tags/PLUGIN slashjp/branches/upstream/current/plugins/Tags/Tags.pm slashjp/branches/upstream/current/plugins/Tags/mysql_dump.sql slashjp/branches/upstream/current/plugins/Tags/mysql_schema.sql slashjp/branches/upstream/current/plugins/Tags/tagbox.pl slashjp/branches/upstream/current/plugins/Tags/templates/tagsstorydivtagbox;misc;default slashjp/branches/upstream/current/sql/mysql/defaults.sql slashjp/branches/upstream/current/sql/mysql/upgrades slashjp/branches/upstream/current/tagboxes/Despam/Despam.pm slashjp/branches/upstream/current/themes/slashcode/THEME slashjp/branches/upstream/current/themes/slashcode/htdocs/comments.pl slashjp/branches/upstream/current/themes/slashcode/htdocs/images/comments.js slashjp/branches/upstream/current/themes/slashcode/htdocs/images/dumper.js slashjp/branches/upstream/current/themes/slashcode/templates/dispComment;misc;default slashjp/branches/upstream/current/themes/slashcode/templates/dispLinkComment;misc;default slashjp/branches/upstream/current/themes/slashcode/templates/dispStory;misc;default slashjp/branches/upstream/current/themes/slashcode/templates/errors;comments;default slashjp/branches/upstream/current/themes/slashcode/templates/html-header;misc;default slashjp/branches/upstream/current/themes/slashcode/templates/modCommentLog;misc;default slashjp/branches/upstream/current/themes/slashcode/templates/printCommComments;misc;default slashjp/branches/upstream/current/themes/slashcode/templates/printCommentsMain;misc;default Added Paths: ----------- slashjp/branches/upstream/current/plugins/Ajax/htdocs/images/jquery-1.2.3.js slashjp/branches/upstream/current/plugins/FireHose/templates/tagsnodnixuser;misc;default slashjp/branches/upstream/current/plugins/Tags/tags_tagnamecache.pl Removed Paths: ------------- slashjp/branches/upstream/current/plugins/Ajax/htdocs/images/prototype.js slashjp/branches/upstream/current/themes/slashcode/htdocs/images/comments2.js -------------- next part -------------- Modified: slashjp/branches/upstream/current/AUTHORS =================================================================== --- slashjp/branches/upstream/current/AUTHORS 2008-03-31 12:09:17 UTC (rev 559) +++ slashjp/branches/upstream/current/AUTHORS 2008-04-01 03:35:14 UTC (rev 560) @@ -8,6 +8,7 @@ Cliff Wood cliff****@slash***** Jamie McCarthy jamie****@mccar***** Tim Vroom vroom****@slash***** + Scott Collins scc****@slash***** Special thanks to some of the outstanding contributors to Slash, who have helped with various kinds of feedback, all of it invaluable. @@ -36,5 +37,5 @@ chromatic chrom****@rmci***** Dan Stahlke dans****@infoi***** -# $Id: AUTHORS,v 1.10 2005/03/11 19:57:18 pudge Exp $ +# $Id: AUTHORS,v 1.11 2008/03/17 02:20:35 scc Exp $ Modified: slashjp/branches/upstream/current/INSTALL =================================================================== --- slashjp/branches/upstream/current/INSTALL 2008-03-31 12:09:17 UTC (rev 559) +++ slashjp/branches/upstream/current/INSTALL 2008-04-01 03:35:14 UTC (rev 560) @@ -71,7 +71,7 @@ The version of this file that you are currently reading is: - $Id: INSTALL,v 1.55 2008/02/20 17:46:57 jamiemccarthy Exp $ + $Id: INSTALL,v 1.56 2008/03/12 17:02:02 jamiemccarthy Exp $ If there are more recent versions of this file, you can find a list of those changes at: @@ -261,6 +261,14 @@ cpan> o conf prerequisites_policy follow cpan> o conf commit + Data::JavaScript::Anon + There are bugs in versions earlier than 1.00 that break our + JS. Unfortunately, CPAN seems to prefer version 0.9 even + though 1.00 is available. You may have to install a better + version in CPAN by hand: + + cpan> install A/AD/ADAMK/Data-JavaScript-Anon-1.00.tar.gz + Additional Libraries You must have certain libraries existing on your system before building, for Compress::Zlib, XML::Parser, DBI and @@ -1475,5 +1483,5 @@ https://lists.sourceforge.net/lists/listinfo/slashcode-announce VERSION - $Id: INSTALL,v 1.55 2008/02/20 17:46:57 jamiemccarthy Exp $ + $Id: INSTALL,v 1.56 2008/03/12 17:02:02 jamiemccarthy Exp $ Modified: slashjp/branches/upstream/current/Slash/DB/MySQL/MySQL.pm =================================================================== --- slashjp/branches/upstream/current/Slash/DB/MySQL/MySQL.pm 2008-03-31 12:09:17 UTC (rev 559) +++ slashjp/branches/upstream/current/Slash/DB/MySQL/MySQL.pm 2008-04-01 03:35:14 UTC (rev 560) @@ -1,7 +1,7 @@ # This code is a part of Slash, and is released under the GPL. # Copyright 1997-2005 by Open Source Technology Group. See README # and COPYING for more information, or see http://slashcode.com/. -# $Id: MySQL.pm,v 1.1008 2008/02/13 17:00:41 jamiemccarthy Exp $ +# $Id: MySQL.pm,v 1.1010 2008/03/21 03:05:35 pudge Exp $ package Slash::DB::MySQL; use strict; @@ -20,7 +20,7 @@ use base 'Slash::DB::Utility'; use Slash::Constants ':messages'; -($VERSION) = ' $Revision: 1.1008 $ ' =~ /\$Revision:\s+([^\s]+)/; +($VERSION) = ' $Revision: 1.1010 $ ' =~ /\$Revision:\s+([^\s]+)/; # Fry: How can I live my life if I can't tell good from evil? @@ -513,7 +513,7 @@ my $page = $user->{currentPage}; my $skin = getCurrentSkin('name'); my $admin = $user->{is_admin}; - my $theme = $user->{simpledesign} ? "light" : $user->{css_theme}; + my $theme = ($user->{simpledesign} || $user->{pda}) ? "light" : $user->{css_theme}; my $constants = getCurrentStatic(); my $expire_time = $constants->{css_expire} || 3600; @@ -532,7 +532,7 @@ $css_skins_ref = $self->getCSSValuesHashForCol('skin') if !$css_skins_ref; $css_themes_ref= $self->getCSSValuesHashForCol('theme') if !$css_themes_ref; - my $lowbandwidth = $user->{lowbandwidth} ? "yes" : "no"; + my $lowbandwidth = ($user->{lowbandwidth} || $user->{pda}) ? "yes" : "no"; $page = '' if !$css_pages_ref->{$page}; $skin = '' if !$css_skins_ref->{$skin}; @@ -7914,15 +7914,16 @@ } sub getSignoffCountHashForStoids { - my($self, $stoids) = @_; + my($self, $stoids, $adminsonly) = @_; return {} if !@$stoids; my $stoid_list = join ',', @$stoids; + my $user_limit_clause = $adminsonly ? ' AND seclev >= 100' : ''; my $signoff_hash = $self->sqlSelectAllHashref( "stoid", - "stoid, COUNT(DISTINCT uid) AS cnt", - "signoff", - "stoid in ($stoid_list)", + "stoid, COUNT(DISTINCT signoff.uid) AS cnt", + "signoff, users", + "users.uid = signoff.uid AND stoid IN ($stoid_list) $user_limit_clause", "GROUP BY stoid" ); Modified: slashjp/branches/upstream/current/Slash/Hook/Hook.pm =================================================================== --- slashjp/branches/upstream/current/Slash/Hook/Hook.pm 2008-03-31 12:09:17 UTC (rev 559) +++ slashjp/branches/upstream/current/Slash/Hook/Hook.pm 2008-04-01 03:35:14 UTC (rev 560) @@ -1,13 +1,10 @@ # This code is a part of Slash, and is released under the GPL. # Copyright 1997-2005 by Open Source Technology Group. See README # and COPYING for more information, or see http://slashcode.com/. -# $Id: Hook.pm,v 1.11 2008/02/28 19:26:58 pudge Exp $ +# $Id: Hook.pm,v 1.12 2008/03/04 21:49:10 pudge Exp $ package Slash::Hook; use strict; -use DBIx::Password; -use Slash; -use Slash::DB; use Slash::Utility::Environment; # avoid cross-caller issues use vars qw($VERSION); @@ -16,7 +13,7 @@ use base 'Exporter'; use vars qw($VERSION @EXPORT); -($VERSION) = ' $Revision: 1.11 $ ' =~ /\$Revision:\s+([^\s]+)/; +($VERSION) = ' $Revision: 1.12 $ ' =~ /\$Revision:\s+([^\s]+)/; @EXPORT = qw(slashHook); my %classes; Modified: slashjp/branches/upstream/current/Slash/Slash.pm =================================================================== --- slashjp/branches/upstream/current/Slash/Slash.pm 2008-03-31 12:09:17 UTC (rev 559) +++ slashjp/branches/upstream/current/Slash/Slash.pm 2008-04-01 03:35:14 UTC (rev 560) @@ -1,7 +1,7 @@ # This code is a part of Slash, and is released under the GPL. # Copyright 1997-2005 by Open Source Technology Group. See README # and COPYING for more information, or see http://slashcode.com/. -# $Id: Slash.pm,v 1.348 2008/02/21 01:01:52 pudge Exp $ +# $Id: Slash.pm,v 1.349 2008/03/18 20:40:15 tvroom Exp $ package Slash; @@ -217,6 +217,7 @@ && $story->{rendered} && !$options->{force_cache_freshen} && !$form->{simpledesign} && !$user->{simpledesign} && !$form->{lowbandwidth} && !$user->{lowbandwidth} + && !$form->{pda} && !$user->{pda} && (!$form->{ssi} || $form->{ssi} ne 'yes') && !$user->{noicons} && !$form->{issue} Modified: slashjp/branches/upstream/current/Slash/Utility/Comments/Comments.pm =================================================================== --- slashjp/branches/upstream/current/Slash/Utility/Comments/Comments.pm 2008-03-31 12:09:17 UTC (rev 559) +++ slashjp/branches/upstream/current/Slash/Utility/Comments/Comments.pm 2008-04-01 03:35:14 UTC (rev 560) @@ -1,7 +1,7 @@ # This code is a part of Slash, and is released under the GPL. # Copyright 1997-2005 by Open Source Technology Group. See README # and COPYING for more information, or see http://slashcode.com/. -# $Id: Comments.pm,v 1.2 2008/02/28 19:26:58 pudge Exp $ +# $Id: Comments.pm,v 1.9 2008/03/20 07:30:29 pudge Exp $ package Slash::Utility::Comments; @@ -34,11 +34,11 @@ use base 'Exporter'; use vars qw($VERSION @EXPORT); -($VERSION) = ' $Revision: 1.2 $ ' =~ /\$Revision:\s+([^\s]+)/; +($VERSION) = ' $Revision: 1.9 $ ' =~ /\$Revision:\s+([^\s]+)/; @EXPORT = qw( constrain_score dispComment displayThread printComments jsSelectComments commentCountThreshold commentThresholds discussion2 - tempUofmLinkGenerate tempUofmCipherObj selectComments + tempUofmLinkGenerate tempUofmCipherObj selectComments preProcessReplyForm getPoints preProcessComment postProcessComment prevComment saveComment ); @@ -405,8 +405,9 @@ my $anon_thresh = Data::JavaScript::Anon->anon_dump($thresh_totals || {}); s/\s+//g for ($anon_thresh, $anon_roots, $anon_rootsh); - $user->{is_anon} ||= 0; - $user->{is_admin} ||= 0; + $user->{is_anon} ||= 0; + $user->{is_admin} ||= 0; + $user->{is_subscriber} ||= 0; my $extra = ''; if ($d2_seen_0) { @@ -442,6 +443,7 @@ user_uid = $user->{uid}; user_is_anon = $user->{is_anon}; user_is_admin = $user->{is_admin}; +user_is_subscriber = $user->{is_subscriber}; user_threshold = $threshold; user_highlightthresh = $highlightthresh; @@ -534,6 +536,17 @@ my($value, $hashref, $nocomm) = @_; $hashref ||= {}; $hashref->{value} = $value; + + # this is a cheap hack to NOT print titlebar in getError if we + # are calling from ajax.pl ... easier than reorganizing the code + # for now -- pudge 2008/03/04 + for (0..9) { + if ((caller($_))[1] =~ /\bajax\.pl$/) { + $hashref->{no_titlebar} = 1; + last; + } + } + return slashDisplay('errors', $hashref, { Return => 1, Nocomm => $nocomm, Page => 'comments' }); } @@ -587,7 +600,7 @@ # Adjust reasons. Do we need a reason? # Are you threatening me? - if ($reasons) { + if ($reasons && $C->{reason}) { my $reason_name = $reasons->{$C->{reason}}{name}; if ($reason_name && $user->{"reason_alter_$reason_name"}) { $hr->{reason_bonus} = @@ -599,7 +612,7 @@ # Keep your friends close but your enemies closer. # Or ignore them, we don't care. - if ($user->{uid} != $C->{uid}) { + if ($user->{people} && $user->{uid} != $C->{uid}) { if ($user->{people}{FRIEND()}{$C->{uid}}) { $hr->{people_bonus_friend} = $user->{people_bonus_friend}; @@ -1322,6 +1335,18 @@ #======================================================================== +sub preProcessReplyForm { + my($form, $reply) = @_; + return if !$form->{pid} || !$reply->{subject} || $form->{postersubj}; + + $form->{postersubj} = decode_entities($reply->{subject}); + $form->{postersubj} =~ s/^Re://i; + $form->{postersubj} =~ s/\s\s/ /g; + $form->{postersubj} = "Re:$form->{postersubj}"; +} + +#======================================================================== + sub preProcessComment { my($comm, $user, $discussion, $error_message) = @_; # probably $comm = $form my $constants = getCurrentStatic(); @@ -1336,7 +1361,7 @@ my $tempSubject = strip_notags($comm->{postersubj}); my $tempComment = $comm->{postercomment}; - $comm->{anon} = 0; + $comm->{anon} = $user->{is_anon}; if ($comm->{postanon} && $reader->checkAllowAnonymousPosting && $user->{karma} > -1 @@ -1407,22 +1432,23 @@ $comm->{comment} = parseDomainTags($comm->{comment}, !$comm->{anon} && $comm->{fakeemail}); -# my $discussion = $slashdb->getDiscussion($comm->{sid}) || 0; my $extras = []; my $disc_skin = $slashdb->getSkin($discussion->{primaryskid}); $extras = $slashdb->getNexusExtrasForChosen( { $disc_skin->{nexus} => 1 }, { content_type => "comment" }) if $disc_skin && $disc_skin->{nexus}; - + my $preview = { - nickname => $comm->{postanon} + nickname => $comm->{anon} ? getCurrentAnonymousCoward('nickname') : $comm->{nickname}, + uid => $comm->{anon} + ? getCurrentAnonymousCoward('uid') + : $comm->{uid}, pid => $comm->{pid}, - uid => $comm->{postanon} ? '' : $comm->{uid}, - homepage => $comm->{postanon} ? '' : $comm->{homepage}, - fakeemail => $comm->{postanon} ? '' : $comm->{fakeemail}, + homepage => $comm->{anon} ? '' : $comm->{homepage}, + fakeemail => $comm->{anon} ? '' : $comm->{fakeemail}, journal_last_entry_date => $comm->{journal_last_entry_date} || '', 'time' => $slashdb->getTime, subject => $comm->{subject}, @@ -1567,7 +1593,7 @@ my $moddb = getObject("Slash::$constants->{m1_pluginname}"); if ($moddb) { my $text = $moddb->checkDiscussionForUndoModeration($comm->{sid}); - # XXX + # XXX doesn't work for D2 print $text if $text; } @@ -1600,13 +1626,16 @@ my $users = $messages->checkMessageCodes(MSG_CODE_COMMENT_REPLY, [$parent->{uid}]); if (_send_comment_msg($users->[0], \%users, $pts, $clean_comment)) { my $data = { - template_name => 'reply_msg', - subject => { template_name => 'reply_msg_subj' }, - reply => $reply, - parent => $parent, - discussion => $discussion, + template_name => 'reply_msg', + template_page => 'comments', + subject => { + template_name => 'reply_msg_subj', + template_page => 'comments', + }, + reply => $reply, + parent => $parent, + discussion => $discussion, }; - $messages->create($users->[0], MSG_CODE_COMMENT_REPLY, $data); $users{$users->[0]}++; } @@ -1617,10 +1646,14 @@ my $users = $messages->checkMessageCodes(MSG_CODE_JOURNAL_REPLY, [$discussion->{uid}]); if (_send_comment_msg($users->[0], \%users, $pts, $clean_comment)) { my $data = { - template_name => 'journrep', - subject => { template_name => 'journrep_subj' }, - reply => $reply, - discussion => $discussion, + template_name => 'journrep', + template_page => 'comments', + subject => { + template_name => 'journrep_subj', + template_page => 'comments', + }, + reply => $reply, + discussion => $discussion, }; $messages->create($users->[0], MSG_CODE_JOURNAL_REPLY, $data); @@ -1633,10 +1666,14 @@ my $users = $messages->getMessageUsers(MSG_CODE_NEW_COMMENT); my $data = { - template_name => 'commnew', - subject => { template_name => 'commnew_subj' }, - reply => $reply, - discussion => $discussion, + template_name => 'commnew', + template_page => 'comments', + subject => { + template_name => 'commnew_subj', + template_page => 'comments', + }, + reply => $reply, + discussion => $discussion, }; my @users_send; @@ -1845,12 +1882,18 @@ $time_to_display = timeCalc($comment->{date}); unless ($user->{noscores}) { - $score_to_display .= " (Score:"; - $score_to_display .= length($comment->{points}) ? $comment->{points} : "?"; + $score_to_display .= "Score:"; + if (length $comment->{points}) { + $score_to_display .= $comment->{points}; + $score_to_display = qq[<a href="#" onclick="getModalPrefs('modcommentlog', 'Moderation Comment Log', $comment->{cid}); return false">$score_to_display</a>] + if $constants->{modal_prefs_active} && !$user->{is_anon}; + } else { + $score_to_display .= '?'; + } if ($reasons && $comment->{reason}) { $score_to_display .= ", $reasons->{$comment->{reason}}{name}"; } - $score_to_display .= ")"; + $score_to_display = " ($score_to_display)"; } if ($comment->{sid} && $comment->{cid}) { @@ -1931,14 +1974,14 @@ && $comment->{nickname} ne "-") { # this last test probably useless my @link = ( ); - push @link, linkComment({ + push @link, (qq'<span id="reply_link_$comment->{cid}">' . linkComment({ sid => $comment->{sid}, pid => $comment->{cid}, op => 'Reply', subject => 'Reply to This', subject_only => 1, - onclick => (($discussion2 && $user->{test_code}) ? "replyTo($comment->{cid}); return false;" : '') - }) unless $user->{state}{discussion_archived}; + onclick => (($discussion2 && (!$constants->{subscribe} || $user->{is_subscriber})) ? "replyTo($comment->{cid}); return false;" : '') + }) . '</span>') unless $user->{state}{discussion_archived}; push @link, linkComment({ sid => $comment->{sid}, @@ -2138,6 +2181,7 @@ # some commonly-used proxy ports to access our own site. # If we can, they're coming from an open HTTP proxy, which # we don't want to allow to post. + # XXX : this can become a reskey check -- pudge 2008-03 if ($constants->{comments_portscan} && ( $constants->{comments_portscan} == 2 || $constants->{comments_portscan} == 1 && $user->{is_anon} ) @@ -2490,4 +2534,4 @@ =head1 VERSION -$Id: Comments.pm,v 1.2 2008/02/28 19:26:58 pudge Exp $ +$Id: Comments.pm,v 1.9 2008/03/20 07:30:29 pudge Exp $ Modified: slashjp/branches/upstream/current/Slash/Utility/Environment/Environment.pm =================================================================== --- slashjp/branches/upstream/current/Slash/Utility/Environment/Environment.pm 2008-03-31 12:09:17 UTC (rev 559) +++ slashjp/branches/upstream/current/Slash/Utility/Environment/Environment.pm 2008-04-01 03:35:14 UTC (rev 560) @@ -1,7 +1,7 @@ # This code is a part of Slash, and is released under the GPL. # Copyright 1997-2005 by Open Source Technology Group. See README # and COPYING for more information, or see http://slashcode.com/. -# $Id: Environment.pm,v 1.234 2008/02/28 19:26:58 pudge Exp $ +# $Id: Environment.pm,v 1.235 2008/03/18 20:39:17 tvroom Exp $ package Slash::Utility::Environment; @@ -33,7 +33,7 @@ use base 'Exporter'; use vars qw($VERSION @EXPORT); -($VERSION) = ' $Revision: 1.234 $ ' =~ /\$Revision:\s+([^\s]+)/; +($VERSION) = ' $Revision: 1.235 $ ' =~ /\$Revision:\s+([^\s]+)/; @EXPORT = qw( dbAvailable @@ -1554,7 +1554,7 @@ my @defaults = ( ['mode', 'thread'], qw[ savechanges commentsort threshold - posttype noboxes lowbandwidth simpledesign + posttype noboxes lowbandwidth simpledesign pda ]); for my $param (@defaults) { @@ -3526,4 +3526,4 @@ =head1 VERSION -$Id: Environment.pm,v 1.234 2008/02/28 19:26:58 pudge Exp $ +$Id: Environment.pm,v 1.235 2008/03/18 20:39:17 tvroom Exp $ Modified: slashjp/branches/upstream/current/bin/install-slashsite =================================================================== --- slashjp/branches/upstream/current/bin/install-slashsite 2008-03-31 12:09:17 UTC (rev 559) +++ slashjp/branches/upstream/current/bin/install-slashsite 2008-04-01 03:35:14 UTC (rev 560) @@ -2,7 +2,7 @@ # This code is a part of Slash, and is released under the GPL. # Copyright 1997-2005 by Open Source Technology Group. See README # and COPYING for more information, or see http://slashcode.com/. -# $Id: install-slashsite,v 1.49 2007/08/30 20:54:21 jamiemccarthy Exp $ +# $Id: install-slashsite,v 1.50 2008/03/07 15:58:53 jamiemccarthy Exp $ # This is the uber install script. # -Brian (brian****@tange*****) @@ -20,13 +20,13 @@ use Slash::DB; use Slash::Install; -(my $VERSION) = ' $Revision: 1.49 $ ' =~ /\$Revision:\s+([^\s]+)/; +(my $VERSION) = ' $Revision: 1.50 $ ' =~ /\$Revision:\s+([^\s]+)/; my $PROGNAME = basename($0); (my $SLASH_PREFIX = $Bin) =~ s|/[^/]+/?$||; my %opts; # Remember to doublecheck these match usage()! -usage('Options used incorrectly') unless getopts('hvu:H:n:xRL:i:T:P:a:e:p:o:g:', \%opts); +usage('Options used incorrectly') unless getopts('hvfu:H:n:xRL:i:T:P:a:e:p:o:g:', \%opts); usage() if !$opts{'u'} and ($opts{'h'} or !keys %opts); # if invoked with both -u and -h, call usage() later, after we load Slash::Install version() if $opts{'v'}; Modified: slashjp/branches/upstream/current/docs/INSTALL.pod =================================================================== --- slashjp/branches/upstream/current/docs/INSTALL.pod 2008-03-31 12:09:17 UTC (rev 559) +++ slashjp/branches/upstream/current/docs/INSTALL.pod 2008-04-01 03:35:14 UTC (rev 560) @@ -104,7 +104,7 @@ The version of this file that you are currently reading is: -$Id: INSTALL.pod,v 1.64 2008/02/19 18:29:04 scc Exp $ +$Id: INSTALL.pod,v 1.65 2008/03/12 15:16:09 scc Exp $ If there are more recent versions of this file, you can find a list of those changes at: @@ -311,6 +311,14 @@ cpan> o conf prerequisites_policy follow cpan> o conf commit +=item B<Data::JavaScript::Anon> + +There are bugs in versions earlier than 1.00 that break our JS. Unfortunately, +CPAN seems to prefer version 0.9 even though 1.00 is available. You may +have to install a better version in CPAN by hand: + + cpan> install A/AD/ADAMK/Data-JavaScript-Anon-1.00.tar.gz + =item B<Additional Libraries> You must have certain libraries existing on your system before building, @@ -1757,5 +1765,5 @@ =head1 VERSION -$Id: INSTALL.pod,v 1.64 2008/02/19 18:29:04 scc Exp $ +$Id: INSTALL.pod,v 1.65 2008/03/12 15:16:09 scc Exp $ Modified: slashjp/branches/upstream/current/plugins/Admin/Admin.pm =================================================================== --- slashjp/branches/upstream/current/plugins/Admin/Admin.pm 2008-03-31 12:09:17 UTC (rev 559) +++ slashjp/branches/upstream/current/plugins/Admin/Admin.pm 2008-04-01 03:35:14 UTC (rev 560) @@ -1,7 +1,7 @@ # This code is a part of Slash, and is released under the GPL. # Copyright 1997-2005 by Open Source Technology Group. See README # and COPYING for more information, or see http://slashcode.com/. -# $Id: Admin.pm,v 1.38 2007/12/13 21:22:53 pudge Exp $ +# $Id: Admin.pm,v 1.39 2008/03/18 16:13:45 tvroom Exp $ package Slash::Admin; @@ -16,7 +16,7 @@ use base 'Slash::DB::Utility'; use base 'Slash::DB::MySQL'; -($VERSION) = ' $Revision: 1.38 $ ' =~ /\$Revision:\s+([^\s]+)/; +($VERSION) = ' $Revision: 1.39 $ ' =~ /\$Revision:\s+([^\s]+)/; # On a side note, I am not sure if I liked the way I named the methods either. # -Brian @@ -221,7 +221,7 @@ my $slashdb = getCurrentDB(); my $form = getCurrentForm(); my $user = getCurrentUser(); - return unless $user->{is_admin}; + return unless $user->{is_admin} || $user->{acl}{signoff_allowed}; my $stoid = $form->{stoid}; my $uid = $user->{uid}; @@ -326,11 +326,11 @@ my($self, $days) = @_; my $days_q = $self->sqlQuote($days); my $signoff_info = $self->sqlSelectAllHashrefArray( - "stories.stoid, users.uid, (unix_timestamp(min(signoff_time)) - unix_timestamp(stories.time)) / 60 AS min_to_sign, users.nickname", + "stories.stoid, users.uid, (unix_timestamp(min(signoff_time)) - unix_timestamp(stories.time)) / 60 AS min_to_sign, users.nickname, users.seclev", "stories, story_topics_rendered, signoff, users", "stories.stoid = story_topics_rendered.stoid AND signoff.stoid=stories.stoid AND users.uid = signoff.uid AND stories.time <= NOW() AND stories.time > DATE_SUB(NOW(), INTERVAL $days_q DAY)", - "GROUP BY signoff.uid, signoff.stoid" + "GROUP BY signoff.uid, signoff.stoid ORDER BY users.seclev DESC" ); return $signoff_info; Modified: slashjp/branches/upstream/current/plugins/Admin/admin.pl =================================================================== --- slashjp/branches/upstream/current/plugins/Admin/admin.pl 2008-03-31 12:09:17 UTC (rev 559) +++ slashjp/branches/upstream/current/plugins/Admin/admin.pl 2008-04-01 03:35:14 UTC (rev 560) @@ -2,7 +2,7 @@ # This code is a part of Slash, and is released under the GPL. # Copyright 1997-2005 by Open Source Technology Group. See README # and COPYING for more information, or see http://slashcode.com/. -# $Id: admin.pl,v 1.331 2008/02/27 19:00:15 jamiemccarthy Exp $ +# $Id: admin.pl,v 1.332 2008/03/18 16:13:45 tvroom Exp $ use strict; use File::Temp 'tempfile'; @@ -1882,7 +1882,7 @@ } my $usersignoffs = $slashdb->getUserSignoffHashForStoids($user->{uid}, $stoid_list); - my $storysignoffcnt = $slashdb->getSignoffCountHashForStoids($stoid_list); + my $storysignoffcnt = $slashdb->getSignoffCountHashForStoids($stoid_list, 1); my $needed_signoffs = $slashdb->getActiveAdminCount; @@ -2601,15 +2601,22 @@ my $signoff_info = $admin->getSignoffData($days); foreach (@$signoff_info) { $author_info->{$_->{uid}}{nickname} = $_->{nickname}; + $author_info->{$_->{uid}}{uid} = $_->{uid}; $author_info->{$_->{uid}}{$days}{cnt}++; $author_info->{$_->{uid}}{$days}{tot_time} += $_->{min_to_sign}; + $author_info->{$_->{uid}}{seclev} = $_->{seclev}; $stoids_for_days{$days}{$_->{stoid}}++; push @{$author_info->{$_->{uid}}{$days}{mins}}, $_->{min_to_sign}; } } + my @author_array = values %$author_info; + + @author_array = sort { $b->{seclev} <=> $a->{seclev} } @author_array; + slashDisplay("signoff_stats", { author_info => $author_info, + author_array => \@author_array, stoids_for_days => \%stoids_for_days, num_days => $num_days }); Modified: slashjp/branches/upstream/current/plugins/Admin/templates/editStory;admin;default =================================================================== --- slashjp/branches/upstream/current/plugins/Admin/templates/editStory;admin;default 2008-03-31 12:09:17 UTC (rev 559) +++ slashjp/branches/upstream/current/plugins/Admin/templates/editStory;admin;default 2008-04-01 03:35:14 UTC (rev 560) @@ -248,7 +248,7 @@ <a href="[% constants.rootdir %]/admin.pl?op=static_files&sid=[% sid %]">Media Files associated with this story</a> </label> <table cellpadding="3" cellspacing="3"> - <tr><td>Select <br>Thumb</td><td colspan="3"></td><td>Click to <br>add to body</td></tr> + <tr><td>Select <br>Thumb</td><td colspan="3"></td><td>Click to <br>add to body</td><td>Click to add<br>to media</td></tr> [% FOREACH mfile = story_static_files %] [% bigfile = mfile.name %] [% IF mfile.filetype != "image" || (mfile.filetype == "image" && bigfile.match('-thumb\.')) %] @@ -269,11 +269,18 @@ [% height = height.int %] [% END %] [% bigfile = bigfile.replace('-thumb') %] - <a href="#bodytext" onclick="appendToBodytext('\n<a href=\'[% constants.imagedir %][% bigfile %]\'><img src=\'[% constants.imagedir %][% mfile.name %]\' width=\'[% mfile.width %]\' height=\'[% mfile.height %]\'></a>')"><img src="[% constants.imagedir %][% mfile.name %]" width="[% width %]" height="[% height %]"></a> + <a href="#bodytext" onclick="appendToBodytext('\n<img src=\'[% constants.imagedir %][% bigfile %]\'>')"><img src="[% constants.imagedir %][% mfile.name %]" width="[% width %]" height="[% height %]"></a> [% ELSE %] <a href="#bodytext" onclick="appendToBodytext('\n<a href=\'[% constants.imagedir %][% mfile.name %]\'>[% filename %]</a>')">Add [% filename %]</a> [% END %] </td> +<td> + [% IF mfile.filetype == "image" %] + <a href="#media" onclick="appendToMedia('\n<img src=\'[% constants.imagedir %][% bigfile %]\'>')"><img src="[% constants.imagedir %][% mfile.name %]" width="[% width %]" height="[% height %]"></a> + [% ELSE %] + <a href="#media" onclick="appendToMedia('\n<a href=\'[% constants.imagedir %][% mfile.name %]\'>[% filename %]</a>')">Add [% filename %]</a> + [% END %] +</td> </tr> [% END %] [% END %] @@ -293,6 +300,7 @@ <label> <a href="#" onclick="toggleId('admin-media','hide','show'); return false">Media</a> </label> + <a name="media"></a> <textarea name="media" rows="[% user.textarea_rows || constants.textarea_rows %]" cols="[% user.textarea_cols || constants.textarea_cols %]" wrap="virtual" id="admin-media" class="[% storyref.media ? "show" : "hide" %]">[% storyref.media | strip_literal %]</textarea> <div class="notes">[% ispell_comments.bodytext %]</div> [% PROCESS editbuttons %] @@ -305,4 +313,4 @@ __seclev__ 10000 __version__ -$Id: editStory;admin;default,v 1.81 2007/11/29 16:53:20 entweichen Exp $ +$Id: editStory;admin;default,v 1.83 2008/03/19 17:45:03 tvroom Exp $ Modified: slashjp/branches/upstream/current/plugins/Admin/templates/signoff;misc;default =================================================================== --- slashjp/branches/upstream/current/plugins/Admin/templates/signoff;misc;default 2008-03-31 12:09:17 UTC (rev 559) +++ slashjp/branches/upstream/current/plugins/Admin/templates/signoff;misc;default 2008-04-01 03:35:14 UTC (rev 560) @@ -18,10 +18,9 @@ [% IF storylink %] <li class="signoff">[% END %] , <span id="signoff_[% stoid %]" onclick="admin_signoff([% stoid %][% IF fhid; ",'firehose',"; fhid; END %])">[% UNLESS signed %]unsigned[% END %]</span> -[% PROCESS ajax_reskey_signoff reskey_label => 'signoff-reskey-' _ stoid, reskey_name => 'ajax_admin' %] [% IF storylink %]</li>[% END %] [% END %] __seclev__ 10000 __version__ -$Id: signoff;misc;default,v 1.15 2007/07/30 18:46:15 tvroom Exp $ +$Id: signoff;misc;default,v 1.16 2008/03/18 16:13:45 tvroom Exp $ Modified: slashjp/branches/upstream/current/plugins/Admin/templates/signoff_stats;misc;default =================================================================== --- slashjp/branches/upstream/current/plugins/Admin/templates/signoff_stats;misc;default 2008-03-31 12:09:17 UTC (rev 559) +++ slashjp/branches/upstream/current/plugins/Admin/templates/signoff_stats;misc;default 2008-04-01 03:35:14 UTC (rev 560) @@ -23,16 +23,22 @@ </td> [% END %] </tr> - -[% FOREACH author = author_info.keys %] - <tr class="data_hl1"><td>[% author_info.$author.nickname %]</td> +[% seen_admin = 0 %] +[% separator = 0 %] +[% FOREACH author = author_array %] + [% IF author.seclev >= 100; seen_admin = 1; END %] + [% IF seen_admin && author.seclev < 100 && !separator %] + <tr><td colspan="6"><b>Non-Admins</b></td></tr> + [% separator = 1; %] + [% END %] + <tr class="data_hl1"><td>[% author.nickname %]</td> [% FOREACH days = num_days %] [% num_stories = stoids_for_days.$days.keys.size || 0 %] - [% cnt = author_info.$author.$days.cnt || 0 %] + [% cnt = author.$days.cnt || 0 %] <td>[% cnt %] of [% num_stories %]</td> <td> [% IF cnt > 0 %] - [% avg_time = author_info.$author.$days.tot_time / cnt %] + [% avg_time = author.$days.tot_time / cnt %] [% avg_time.int %] m [% ELSE %] N/A @@ -43,5 +49,5 @@ [% END %] </table> __version__ -$Id: signoff_stats;misc;default,v 1.3 2006/02/27 18:44:08 tvroom Exp $ +$Id: signoff_stats;misc;default,v 1.4 2008/03/18 16:13:45 tvroom Exp $ Modified: slashjp/branches/upstream/current/plugins/Ajax/PLUGIN =================================================================== --- slashjp/branches/upstream/current/plugins/Ajax/PLUGIN 2008-03-31 12:09:17 UTC (rev 559) +++ slashjp/branches/upstream/current/plugins/Ajax/PLUGIN 2008-04-01 03:35:14 UTC (rev 560) @@ -1,4 +1,4 @@ -# $Id: PLUGIN,v 1.40 2008/02/28 19:26:58 pudge Exp $ +# $Id: PLUGIN,v 1.41 2008/03/14 15:48:06 scc Exp $ name=Ajax description="Ajax (Asynchronous Javascript and XML)" mysql_dump=mysql_dump.sql @@ -28,7 +28,7 @@ htdoc=htdocs/images/slashbox.js htdoc=htdocs/images/common.js htdoc=htdocs/images/nodnix.js -htdoc=htdocs/images/prototype.js +htdoc=htdocs/images/jquery-1.2.3.js htdoc=htdocs/images/sectionprefs.js requiresplugin=ResKey template=templates/ajax_reskey_signoff;misc;default Modified: slashjp/branches/upstream/current/plugins/Ajax/htdocs/ajax.pl =================================================================== --- slashjp/branches/upstream/current/plugins/Ajax/htdocs/ajax.pl 2008-03-31 12:09:17 UTC (rev 559) +++ slashjp/branches/upstream/current/plugins/Ajax/htdocs/ajax.pl 2008-04-01 03:35:14 UTC (rev 560) @@ -2,7 +2,7 @@ # This code is a part of Slash, and is released under the GPL. # Copyright 1997-2005 by Open Source Technology Group. See README # and COPYING for more information, or see http://slashcode.com/. -# $Id: ajax.pl,v 1.74 2008/02/28 19:26:58 pudge Exp $ +# $Id: ajax.pl,v 1.77 2008/03/19 08:25:31 pudge Exp $ use strict; use warnings; @@ -14,7 +14,7 @@ use Slash::Utility; use vars qw($VERSION); -($VERSION) = ' $Revision: 1.74 $ ' =~ /\$Revision:\s+([^\s]+)/; +($VERSION) = ' $Revision: 1.77 $ ' =~ /\$Revision:\s+([^\s]+)/; ################################################################## sub main { @@ -54,6 +54,8 @@ # print STDERR "AJAX5 $$: $user->{uid}, $op\n"; + my $options = {}; + if ($reskey_name ne 'NA') { my $reskey = getObject('Slash::ResKey'); my $rkey = $reskey->key($reskey_name); @@ -61,6 +63,7 @@ print STDERR scalar(localtime) . " ajax.pl main no rkey for op='$op' name='$reskey_name'\n"; return; } + $options->{rkey} = $rkey; if ($ops->{$op}{reskey_type} eq 'createuse') { $rkey->createuse; } elsif ($ops->{$op}{reskey_type} eq 'touch') { @@ -85,7 +88,6 @@ } # print STDERR "AJAX6 $$: $user->{uid}, $op\n"; - my $options = {}; my $retval = $ops->{$op}{function}->( $slashdb, $constants, $user, $form, $options ); @@ -273,6 +275,23 @@ my $pid = $form->{pid} || 0; my $sid = $form->{sid} or return; + $user->{state}{ajax_accesslog_op} = 'comments_submit_reply'; + + my($error_message, $saved_comment); + my $discussion = $slashdb->getDiscussion($sid); + my $comment = preProcessComment($form, $user, $discussion, \$error_message); + if (!$error_message) { + $options->{rkey}->use or $error_message = $options->{rkey}->errstr; + } + $saved_comment = saveComment($form, $comment, $user, $discussion, \$error_message) + unless $error_message; + my $cid = $saved_comment && $saved_comment ne '-1' ? $saved_comment->{cid} : 0; + + $options->{content_type} = 'application/json'; + my %to_dump = ( cid => $cid, error => $error_message ); +#use Data::Dumper; print STDERR Dumper \%to_dump; + + return Data::JavaScript::Anon->anon_dump(\%to_dump); } sub previewReply { @@ -282,14 +301,24 @@ $user->{state}{ajax_accesslog_op} = 'comments_preview_reply'; + my($error_message, $preview, $html); my $discussion = $slashdb->getDiscussion($sid); - my $comment = preProcessComment($form, $user, $discussion); - my $preview = postProcessComment({ %$comment, %$user }, 0, $discussion); - my $html = prevComment($preview, $user); + my $comment = preProcessComment($form, $user, $discussion, \$error_message); + if ($comment && $comment ne '-1') { + $preview = postProcessComment({ %$comment, %$form, %$user }, 0, $discussion); + $html = prevComment($preview, $user); + } - + $error_message ||= 'This comment will not be saved until you click the Submit button below.'; $options->{content_type} = 'application/json'; - my %to_dump = (html => { "replyto_preview_$pid" => $html }); + my %to_dump = ( + error => $error_message, + ); + $to_dump{html} = { "replyto_preview_$pid" => $html } if $html; + $to_dump{eval_first} = "\$('gotmodwarning_$pid').value = 1;" + if $form->{gotmodwarning} || ($error_message && $error_message eq + Slash::Utility::Comments::getError("moderations to be lost") + ); #use Data::Dumper; print STDERR Dumper \%to_dump; return Data::JavaScript::Anon->anon_dump(\%to_dump); @@ -304,8 +333,10 @@ $user->{state}{ajax_accesslog_op} = 'comments_reply_form'; my($reply, $pid_reply); + my $discussion = $slashdb->getDiscussion($sid); $reply = $slashdb->getCommentReply($sid, $pid) if $pid; $pid_reply = prepareQuoteReply($reply) if $pid && $reply; + preProcessReplyForm($form, $reply); my $reskey = getObject('Slash::ResKey'); my $rkey = $reskey->key('comments', { nostate => 1 }); @@ -314,10 +345,11 @@ my %to_dump; if ($rkey->success) { my $reply_html = slashDisplay('edit_comment', { - sid => $sid, - pid => $pid, - reply => $reply, - rkey => $rkey + discussion => $discussion, + sid => $sid, + pid => $pid, + reply => $reply, + rkey => $rkey }, { Return => 1 }); %to_dump = (html => { "replyto_$pid" => $reply_html }); } else { @@ -326,7 +358,6 @@ $options->{content_type} = 'application/json'; $to_dump{eval_first} = "comment_body_reply[$pid] = '$pid_reply';" if $pid_reply; - #use Data::Dumper; print STDERR Dumper \%to_dump; return Data::JavaScript::Anon->anon_dump(\%to_dump); @@ -711,6 +742,22 @@ { Page => 'misc', Skin => 'idle', Return => 1 } ); + } elsif ($form->{'section'} eq 'modcommentlog') { + my $moddb = getObject("Slash::$constants->{m1_pluginname}"); + if ($moddb) { + # we hijack "tabbed" as our cid -- pudge + return $moddb->dispModCommentLog('cid', $form->{'tabbed'}, { + show_m2s => ($constants->{m2} + ? (defined($form->{show_m2s}) + ? $form->{show_m2s} + : $user->{m2_with_comm_mod} + ) : 0), + need_m2_form => $constants->{m2}, + need_m2_button => $constants->{m2}, + title => " " + }); + } + } else { return @@ -731,7 +778,7 @@ my $url = URI->new('//e.a/?' . $form->{'data'}); my %params = $url->query_form; - # D2 display + # D2 display my $user_edits_table; if ($params{'formname'} eq 'd2_display') { $user_edits_table = { @@ -744,7 +791,7 @@ }; } - # D2 posting + # D2 posting if ($params{'formname'} eq 'd2_posting') { $user_edits_table = { emaildisplay => $params{'emaildisplay'} || undef, @@ -758,7 +805,17 @@ }; } - # Messages + # Messages + if ($params{'formname'} eq 'metamoderate') { + if ($constants->{m2} && $user->{is_admin}) { + # metaModerate uses $form ... whether it should or not! -- pudge + @$form{keys %params} = values %params; + my $metamod_db = getObject('Slash::Metamod'); + $metamod_db->metaModerate($user->{is_admin}) if $metamod_db; + } + } + + # Messages if ($params{'formname'} eq 'messages') { my $messages = getObject('Slash::Messages'); my $messagecodes = $messages->getDescriptions('messagecodes'); @@ -1043,9 +1100,9 @@ my %mainops = ( comments_submit_reply => { - function => \&previewReply, + function => \&submitReply, reskey_name => 'comments', - reskey_type => 'use', + reskey_type => 'touch', }, comments_preview_reply => { function => \&previewReply, Modified: slashjp/branches/upstream/current/plugins/Ajax/htdocs/images/admin.js =================================================================== --- slashjp/branches/upstream/current/plugins/Ajax/htdocs/images/admin.js 2008-03-31 12:09:17 UTC (rev 559) +++ slashjp/branches/upstream/current/plugins/Ajax/htdocs/images/admin.js 2008-04-01 03:35:14 UTC (rev 560) @@ -1,7 +1,7 @@ -// $Id: admin.js,v 1.44 2007/12/20 18:46:05 tvroom Exp $ +// $Id: admin.js,v 1.48 2008/03/18 16:28:44 tvroom Exp $ function um_ajax(the_behaviors, the_events) { - var params =[]; + var params = {}; params['op'] = 'um_ajax'; params['behaviors'] = the_behaviors; params['events'] = the_events; @@ -9,32 +9,20 @@ } function um_fetch_settings() { - var params =[]; + var params = {}; params['op'] = 'um_fetch_settings'; ajax_update(params, 'links-vendors-content'); } function um_set_settings(behavior) { - var params =[]; + var params = {}; params['op'] = 'um_set_settings'; params['behavior'] = behavior; ajax_update(params, 'links-vendors-content'); } -function admin_signoff(stoid, type, id) { - var params = []; - var reskeyel = $('signoff-reskey-' + stoid); - params['op'] = 'admin_signoff'; - params['stoid'] = stoid; - params['reskey'] = reskeyel.value; - ajax_update(params, 'signoff_' + stoid); - if (type == "firehose") { - firehose_collapse_entry(id); - } -} - function admin_neverdisplay(stoid, type, fhid) { - var params = []; + var params = {}; params['op'] = 'admin_neverdisplay'; params['reskey'] = reskey_static; params['stoid'] = stoid; @@ -48,22 +36,22 @@ } function admin_submit_memory(fhid) { - var params = []; + var params = {}; params['op'] = 'admin_submit_memory'; params['reskey'] = reskey_static; - params['submatch'] = $('submatch-'+fhid).value; - params['subnote'] = $('subnote-'+fhid).value; + params['submatch'] = $dom('submatch-'+fhid).value; + params['subnote'] = $dom('subnote-'+fhid).value; ajax_update(params, 'sub_mem_message-'+fhid); } function adminTagsCommands(id, type) { - var toggletags_message_id = 'toggletags-message-' + id; - var toggletags_message_el = $(toggletags_message_id); + var toggletags_message_id = '#toggletags-message-' + id; + var toggletags_message_el = jQuery(toggletags_message_id)[0]; if (toggletags_message_el) { toggletags_message_el.innerHTML = 'Executing commands...'; } - var params = []; + var params = {}; type = type || "stories"; params['op'] = 'tags_admin_commands'; if (type == "stories") { @@ -74,9 +62,9 @@ params['id'] = id; } params['type'] = type; - var tags_admin_commands_el = $('tags_admin_commands-' + id); + var tags_admin_commands_el = $dom('tags_admin_commands-' + id); params['commands'] = tags_admin_commands_el.value; - var reskeyel = $('admin_commands-reskey-' + id); + var reskeyel = $dom('admin_commands-reskey-' + id); params['reskey'] = reskeyel.value; ajax_update(params, 'tags-admin-' + id); @@ -84,7 +72,7 @@ } function tagsHistory(id, type) { - var params = []; + var params = {}; type = type || "stories"; params['type'] = type; params['op'] = 'tags_history'; @@ -103,17 +91,17 @@ } function remarks_create() { - var reskey = $('remarks_reskey'); - var remark = $('remarks_new'); + var reskey = $dom('remarks_reskey'); + var remark = $dom('remarks_new'); if (!remark || !remark.value || !reskey || !reskey.value) { return false; } - var params = []; + var params = {}; params['op'] = 'remarks_create'; params['remark'] = remark.value; params['reskey'] = reskey.value; - remarks_max = $('remarks_max'); + remarks_max = $dom('remarks_max'); if (remarks_max && remarks_max.value) { params['limit'] = remarks_max.value; } @@ -121,7 +109,7 @@ } function remarks_fetch(secs, limit) { - var params = []; + var params = {}; params['op'] = 'remarks_fetch'; params['limit'] = limit; // run it every 30 seconds; don't need to call again @@ -129,7 +117,7 @@ } function remarks_popup() { - var params = []; + var params = {}; params['op'] = 'remarks_config'; var title = "Remarks Config "; var buttons = createPopupButtons('<a href="#" onclick="closePopup(\'remarksconfig-popup\', 1); return false">[X]</a>'); @@ -140,11 +128,11 @@ } function remarks_config_save() { - var params = []; - var reskey = $('remarks_reskey'); - var min_priority = $('remarks_min_priority'); - var limit = $('remarks_limit'); - var filter = $('remarks_filter'); + var params = {}; + var reskey = $dom('remarks_reskey'); + var min_priority = $dom('remarks_min_priority'); + var limit = $dom('remarks_limit'); + var filter = $dom('remarks_filter'); params['op'] = 'remarks_config_save'; if (!reskey && !reskey.value) { return false; @@ -158,7 +146,7 @@ if (filter) { params['filter'] = filter.value; } - var message = $('remarksconfig-message'); + var message = $dom('remarksconfig-message'); if (message) { message.innerHTML = "Saving..."; } @@ -166,31 +154,31 @@ } function admin_slashdbox_fetch(secs) { - var params = []; + var params = {}; params['op'] = 'admin_slashdbox'; ajax_periodic_update(secs, params, "slashdbox-content"); } function admin_perfbox_fetch(secs) { - var params = []; + var params = {}; params['op'] = 'admin_perfbox'; ajax_periodic_update(secs, params, "performancebox-content"); } function admin_authorbox_fetch(secs) { - var params = []; + var params = {}; params['op'] = 'admin_authorbox'; ajax_periodic_update(secs, params, "authoractivity-content"); } function admin_storyadminbox_fetch(secs) { - var params = []; + var params = {}; params['op'] = 'admin_storyadminbox'; ajax_periodic_update(secs, params, "storyadmin-content"); } function admin_recenttagnamesbox_fetch(secs) { - var params = []; + var params = {}; params['op'] = 'admin_recenttagnamesbox'; ajax_periodic_update(secs, params, "recenttagnames-content"); } @@ -202,7 +190,7 @@ return; } - var params = []; + var params = {}; params['op'] = 'console_update' var handlers = { onComplete: json_handler @@ -216,11 +204,11 @@ } function firehose_usage() { - var params = []; + var params = {}; params['op'] = 'firehose_usage' var interval = 300000; ajax_update(params, 'firehose_usage-content'); - setTimeout("firehose_usage()", interval); + setTimeout(firehose_usage, interval); } function make_spelling_correction(misspelled_word, form_element) { @@ -234,7 +222,7 @@ // Either learning a word or making a correction. if (selected_index >= 1) { if (selected_index == 1) { - var params = []; + var params = {}; params['op'] = 'admin_learnword'; params['word'] = misspelled_word; ajax_update(params); @@ -265,8 +253,8 @@ } function firehose_reject (el) { - var params = []; - var fh = $('firehose-' + el.value); + var params = {}; + var fh = $dom('firehose-' + el.value); params['op'] = 'firehose_reject'; params['id'] = el.value; params['reskey'] = reskey_static; @@ -275,19 +263,19 @@ } function firehose_open_note(id) { - var nf = $('note-form-'+id); - var nt = $('note-text-'+id); - var ni = $('note-input-'+id); + var nf = $dom('note-form-'+id); + var nt = $dom('note-text-'+id); + var ni = $dom('note-input-'+id); nf.className=""; ni.focus(); nt.className="hide"; } function firehose_save_note(id) { - var nf = $('note-form-'+id); - var nt = $('note-text-'+id); - var ni = $('note-input-'+id); - var params = []; + var nf = $dom('note-form-'+id); + var nt = $dom('note-text-'+id); + var ni = $dom('note-input-'+id); + var params = {}; params['op'] = 'firehose_save_note'; params['note'] = ni.value; params['id'] = id; @@ -297,30 +285,43 @@ } function firehose_get_admin_extras(id) { - var params=[]; + var params = {}; params['id'] = id; params['op'] = 'firehose_get_admin_extras'; var handlers = { - onComplete: json_handler + onComplete: function(transport) { + json_handler(transport); + if (firehoseIsInWindow(id)) { + scrollToWindowFirehose(id); + } + } }; ajax_update(params, '', handlers); } function firehose_get_and_post(id) { - var params=[]; + var params = {}; params['id'] = id; params['op'] = 'firehose_get_form'; firehose_collapse_entry(id); var handlers = { - onComplete: function() { $('postform-'+id).submit();} + onComplete: function() { $dom('postform-'+id).submit();} }; ajax_update(params, 'postform-'+id, handlers); } function appendToBodytext(text) { - var obj = $('admin-bodytext'); + var obj = $dom('admin-bodytext'); if (obj) { obj.className = "show"; obj.value = obj.value + text; } } + +function appendToMedia(text) { + var obj = $dom('admin-media'); + if (obj) { + obj.className = "show"; + obj.value = obj.value + text; + } +} Modified: slashjp/branches/upstream/current/plugins/Ajax/htdocs/images/common.js =================================================================== --- slashjp/branches/upstream/current/plugins/Ajax/htdocs/images/common.js 2008-03-31 12:09:17 UTC (rev 559) +++ slashjp/branches/upstream/current/plugins/Ajax/htdocs/images/common.js 2008-04-01 03:35:14 UTC (rev 560) @@ -1,6 +1,10 @@ // _*_ Mode: JavaScript; tab-width: 8; indent-tabs-mode: true _*_ -// $Id: common.js,v 1.174 2008/02/28 19:26:58 pudge Exp $ +// $Id: common.js,v 1.183 2008/03/18 16:28:44 tvroom Exp $ +function $dom( id ) { + return document.getElementById(id); +} + // global settings, but a firehose might use a local settings object instead var firehose_settings = {}; firehose_settings.startdate = ''; @@ -25,6 +29,8 @@ firehose_removals = null; firehose_future = null; + var firehose_cur = 0; + // globals we haven't yet decided to move into |firehose_settings| var fh_play = 0; var fh_is_timed_out = 0; @@ -43,9 +49,6 @@ var is_ie = ua.match("/MSIE/"); -// eventually add site specific constants like this to a separate .js -var sitename = "Slashdot"; - function createPopup(xy, titlebar, name, contents, message, onmouseout) { var body = document.getElementsByTagName("body")[0]; var div = document.createElement("div"); @@ -88,7 +91,7 @@ } function closePopup(id, refresh) { - var el = $(id); + var el = $dom(id); if (el) { el.parentNode.removeChild(el); } @@ -131,8 +134,9 @@ } function getXYForId(id, addWidth, addHeight) { - var div = $(id); - var xy = Position.cumulativeOffset(div); + var div = $dom(id); + var offset = jQuery(div).offset(); + var xy = [ offset.left, offset.top ]; if (addWidth) { xy[0] = xy[0] + div.offsetWidth; } @@ -143,7 +147,7 @@ } function firehose_toggle_advpref() { - var obj = $('fh_advprefs'); + var obj = $dom('fh_advprefs'); if (obj.className == 'hide') { obj.className = ""; } else { @@ -152,12 +156,12 @@ } function firehose_open_prefs() { - var obj = $('fh_advprefs'); + var obj = $dom('fh_advprefs'); obj.className = ""; } function toggleId(id, first, second) { - var obj =$(id); + var obj = $dom(id); if (obj.className == first) { obj.className = second; } else if (obj.className == second) { @@ -168,8 +172,8 @@ } function toggleIntro(id, toggleid) { - var obj = $(id); - var toggle = $(toggleid); + var obj = $dom(id); + var toggle = $dom(toggleid); if (obj.className == 'introhide') { obj.className = "intro" toggle.innerHTML = "[-]"; @@ -183,7 +187,7 @@ function tagsToggleStoryDiv(id, is_admin, type) { var bodyid = 'toggletags-body-' + id; - var tagsbody = $(bodyid); + var tagsbody = $dom(bodyid); if (tagsbody.className == 'tagshide') { tagsShowBody(id, is_admin, '', type); } else { @@ -194,22 +198,22 @@ function tagsHideBody(id) { // Make the body of the tagbox vanish var tagsbodyid = 'toggletags-body-' + id; - var tagsbody = $(tagsbodyid); + var tagsbody = $dom(tagsbodyid); tagsbody.className = "tagshide" // Make the title of the tagbox change back to regular var titleid = 'tagbox-title-' + id; - var title = $(titleid); + var title = $dom(titleid); title.className = "tagtitleclosed"; // Make the tagbox change back to regular. var tagboxid = 'tagbox-' + id; - var tagbox = $(tagboxid); + var tagbox = $dom(tagboxid); tagbox.className = "tags"; // Toggle the button back. var tagsbuttonid = 'toggletags-button-' + id; - var tagsbutton = $(tagsbuttonid); + var tagsbutton = $dom(tagsbuttonid); tagsbutton.innerHTML = "[+]"; } @@ -228,35 +232,35 @@ // Toggle the button to show the click was received var tagsbuttonid = 'toggletags-button-' + id; - var tagsbutton = $(tagsbuttonid); + var tagsbutton = $dom(tagsbuttonid); tagsbutton.innerHTML = "[-]"; // Make the tagbox change to the slashbox class var tagboxid = 'tagbox-' + id; - var tagbox = $(tagboxid); + var tagbox = $dom(tagboxid); tagbox.className = "tags"; // Make the title of the tagbox change to white-on-green var titleid = 'tagbox-title-' + id; - var title = $(titleid); + var title = $dom(titleid); title.className = "tagtitleopen"; // Make the body of the tagbox visible var tagsbodyid = 'toggletags-body-' + id; - var tagsbody = $(tagsbodyid); + var tagsbody = $dom(tagsbodyid); tagsbody.className = "tagbody"; // If the tags-user div hasn't been filled, fill it. var tagsuserid = 'tags-user-' + id; - var tagsuser = $(tagsuserid); + var tagsuser = $dom(tagsuserid); if (tagsuser.innerHTML == "") { // The tags-user-123 div is empty, and needs to be // filled with the tags this user has already // specified for this story, and a reskey to allow // the user to enter more tags. tagsuser.innerHTML = "Retrieving..."; - var params = []; + var params = {}; if (type == "stories") { params['op'] = 'tags_get_user_story'; params['sidenc'] = id; @@ -272,7 +276,7 @@ var handlers = { onComplete: function() { var textid = 'newtags-' + id; - var input = $(textid); + var input = $dom(textid); input.focus(); } } @@ -287,7 +291,7 @@ // user is not actually an admin. if (is_admin) { var tagsadminid = 'tags-admin-' + id; - params = []; + params = {}; if (type == "stories") { params['op'] = 'tags_get_admin_story'; params['sidenc'] = id; @@ -308,7 +312,7 @@ // We can't do that by passing it in, so do it // manually now. var textinputid = 'newtags-' + id; - var textinput = $(textinputid); + var textinput = $dom(textinputid); textinput.value = textinput.value + ' ' + newtagspreloadtext; textinput.focus(); } @@ -382,12 +386,12 @@ } function createTag(tag, id, type) { - var params = []; + var params = {}; params['id'] = id; params['type'] = type; if ( fh_is_admin && ("_#)^*".indexOf(tag[0]) != -1) ) { params['op'] = 'tags_admin_commands'; - params['reskey'] = $('admin_commands-reskey-' + id).value; + params['reskey'] = $dom('admin_commands-reskey-' + id).value; params['command'] = tag; } else { params['op'] = 'tags_create_tag'; @@ -402,15 +406,15 @@ function tagsCreateForStory(id) { var toggletags_message_id = 'toggletags-message-' + id; - var toggletags_message_el = $(toggletags_message_id); + var toggletags_message_el = $dom(toggletags_message_id); toggletags_message_el.innerHTML = 'Saving tags...'; - var params = []; + var params = {}; params['op'] = 'tags_create_for_story'; params['sidenc'] = id; - var newtagsel = $('newtags-' + id); + var newtagsel = $dom('newtags-' + id); params['tags'] = newtagsel.value; - var reskeyel = $('newtags-reskey-' + id); + var reskeyel = $dom('newtags-reskey-' + id); params['reskey'] = reskeyel.value; ajax_update(params, 'tags-user-' + id); @@ -421,15 +425,15 @@ function tagsCreateForUrl(id) { var toggletags_message_id = 'toggletags-message-' + id; - var toggletags_message_el = $(toggletags_message_id); + var toggletags_message_el = $dom(toggletags_message_id); toggletags_message_el.innerHTML = 'Saving tags...'; - var params = []; + var params = {}; params['op'] = 'tags_create_for_url'; params['id'] = id; - var newtagsel = $('newtags-' + id); + var newtagsel = $dom('newtags-' + id); params['tags'] = newtagsel.value; - var reskeyel = $('newtags-reskey-' + id); + var reskeyel = $dom('newtags-reskey-' + id); params['reskey'] = reskeyel.value; ajax_update(params, 'tags-user-' + id); @@ -440,7 +444,7 @@ //Firehose functions begin function setOneTopTagForFirehose(id, newtag) { - var params = []; + var params = {}; params['op'] = 'firehose_update_one_tag'; params['id'] = id; params['tags'] = newtag; @@ -450,15 +454,15 @@ function tagsCreateForFirehose(id) { var toggletags_message_id = 'toggletags-message-' + id; - var toggletags_message_el = $(toggletags_message_id); + var toggletags_message_el = $dom(toggletags_message_id); toggletags_message_el.innerHTML = 'Saving tags...'; - var params = []; + var params = {}; params['op'] = 'tags_create_for_firehose'; params['id'] = id; - var newtagsel = $('newtags-' + id); + var newtagsel = $dom('newtags-' + id); params['tags'] = newtagsel.value; - var reskeyel = $('newtags-reskey-' + id); + var reskeyel = $dom('newtags-reskey-' + id); params['reskey'] = reskeyel.value; ajax_update(params, 'tags-user-' + id); @@ -466,16 +470,19 @@ } function toggle_firehose_body(id, is_admin) { - var params = []; + var params = {}; setFirehoseAction(); params['op'] = 'firehose_fetch_text'; params['id'] = id; - var fhbody = $('fhbody-'+id); - var fh = $('firehose-'+id); + var fhbody = $dom('fhbody-'+id); + var fh = $dom('firehose-'+id); var usertype = fh_is_admin ? " adminmode" : " usermode"; if (fhbody.className == "empty") { var handlers = { - onComplete: function() { + onComplete: function() { + if(firehoseIsInWindow(id)) { + scrollToWindowFirehose(id); + } firehose_get_admin_extras(id); } }; @@ -503,7 +510,7 @@ } function toggleFirehoseTagbox(id) { - var fhtb = $('fhtagbox-'+id); + var fhtb = $dom('fhtagbox-'+id); if (fhtb.className == "hide") { fhtb.className = "tagbox"; } else { @@ -521,7 +528,7 @@ ["mode", "full", "abbrev", "full", "fulltitle"], ["mode", "fulltitle", "full", "abbrev", "full"] ]; - var params = []; + var params = {}; params['op'] = 'firehose_set_options'; params['reskey'] = reskey_static; var theForm = document.forms["firehoseform"]; @@ -548,7 +555,7 @@ } if (classname) { - var els = document.getElementsByClassName(classname, $('firehoselist')); + var els = document.getElementsByClassName(classname, $dom('firehoselist')); var classval = classname; if (value) { classval = classval + " hide"; @@ -572,12 +579,12 @@ var el = pairs[i]; if (name == el[0] && value == el[1]) { firehose_settings[name] = value; - if ($(el[2])) { - $(el[2]).id = el[3]; - if($(el[3])) { + if ($dom(el[2])) { + $dom(el[2]).id = el[3]; + if($dom(el[3])) { var namenew = el[0]; var valuenew = el[4]; - $(el[3]).firstChild.onclick = function() { firehose_set_options(namenew, valuenew); return false;} + $dom(el[3]).firstChild.onclick = function() { firehose_set_options(namenew, valuenew); return false;} } } } @@ -587,7 +594,7 @@ if (name == "mode") { fh_view_mode = value; } - if ($('firehoselist')) { + if ($dom('firehoselist')) { // set page page = 0; @@ -598,12 +605,12 @@ var myAnim = new YAHOO.util.Anim("firehoselist", attributes); myAnim.duration = 1; myAnim.onComplete.subscribe(function() { - $('firehoselist').style.opacity = "1"; + $dom('firehoselist').style.opacity = "1"; }); myAnim.animate(); } // remove elements - setTimeout("firehose_remove_all_items()", 600); + setTimeout(firehose_remove_all_items, 600); } } } @@ -623,11 +630,11 @@ firehose_settings.page = 0; var issuedate = firehose_settings.issue.substr(5,2) + "/" + firehose_settings.issue.substr(8,2) + "/" + firehose_settings.issue.substr(10,2); - if ($('fhcalendar')) { - $('fhcalendar')._widget.setDate(issuedate, "day"); + if ($dom('fhcalendar')) { + $dom('fhcalendar')._widget.setDate(issuedate, "day"); } - if ($('fhcalendar_pag')) { - $('fhcalendar_pag')._widget.setDate(issuedate, "day"); + if ($dom('fhcalendar_pag')) { + $dom('fhcalendar_pag')._widget.setDate(issuedate, "day"); } } if (name == "color") { @@ -662,7 +669,7 @@ } function firehose_remove_all_items() { - var fhl = $('firehoselist'); + var fhl = $dom('firehoselist'); var children = fhl.childNodes; for (var i = children.length -1 ; i >= 0; i--) { var el = children[i]; @@ -677,7 +684,7 @@ if (!check_logged_in()) return; setFirehoseAction(); - var params = []; + var params = {}; var handlers = { onComplete: json_handler }; @@ -685,7 +692,7 @@ params['id'] = id; params['reskey'] = reskey_static; params['dir'] = dir; - var updown = $('updown-' + id); + var updown = $dom('updown-' + id); ajax_update(params, '', handlers); if (updown) { if (dir == "+") { @@ -702,7 +709,7 @@ function firehose_remove_tab(tabid) { setFirehoseAction(); - var params = []; + var params = {}; var handlers = { onComplete: json_handler }; @@ -718,39 +725,34 @@ // firehose functions end // helper functions -function ajax_update(params, onsucc, options, url) { - var h = $H(params); +function ajax_update(request_params, id, handlers, request_url) { + // make an ajax request to request_url with request_params, on success, + // update the innerHTML of the element with id - if (!url) - url = '/ajax.pl'; + var opts = { + url: request_url || '/ajax.pl', + data: request_params, + type: 'POST', + contentType: 'application/x-www-form-urlencoded', + }; - if (!options) - options = {}; + if ( id ) { + opts['success'] = function(html){ + jQuery('#'+id).html(html); + } + } - options.method = 'post'; - options.parameters = h.toQueryString(); + if ( handlers && handlers.onComplete ) { + opts['complete'] = handlers.onComplete; + } - var ajax = new Ajax.Updater( - { success: onsucc }, - url, - options - ); + jQuery.ajax(opts); } -function ajax_periodic_update(secs, params, onsucc, options, url) { - var h = $H(params); - - if (!url) - url = '/ajax.pl'; - - if (!options) - options = {}; - - options.frequency = secs; - options.method = 'post'; - options.parameters = h.toQueryString(); - - var ajax = new Ajax.PeriodicalUpdater({ success: onsucc }, url, options); +function ajax_periodic_update(interval_in_seconds, request_params, id, handlers, request_url) { + setInterval(function(){ + ajax_update(request_params, id, handlers, request_url); + }, interval_in_seconds*1000); } function eval_response(transport) { @@ -766,6 +768,7 @@ function json_handler(transport) { var response = eval_response(transport); json_update(response); + return response; } function json_update(response) { @@ -779,35 +782,35 @@ if (response.html) { for (el in response.html) { - if ($(el)) - $(el).innerHTML = response.html[el]; + if ($dom(el)) + $dom(el).innerHTML = response.html[el]; } } if (response.value) { for (el in response.value) { - if ($(el)) - $(el).value = response.value[el]; + if ($dom(el)) + $dom(el).value = response.value[el]; } } if (response.html_append) { for (el in response.html_append) { - if ($(el)) - $(el).innerHTML = $(el).innerHTML + response.html_append[el]; + if ($dom(el)) + $dom(el).innerHTML = $dom(el).innerHTML + response.html_append[el]; } } if (response.html_append_substr) { for (el in response.html_append_substr) { - if ($(el)) { - var this_html = $(el).innerHTML; - var i = $(el).innerHTML.search(/<span class="?substr"?> ?<\/span>[\s\S]*$/i); + if ($dom(el)) { + var this_html = $dom(el).innerHTML; + var i = $dom(el).innerHTML.search(/<span class="?substr"?> ?<\/span>[\s\S]*$/i); if (i == -1) { - $(el).innerHTML += response.html_append_substr[el]; + $dom(el).innerHTML += response.html_append_substr[el]; } else { - $(el).innerHTML = $(el).innerHTML.substr(0, i) + + $dom(el).innerHTML = $dom(el).innerHTML.substr(0, i) + response.html_append_substr[el]; } } @@ -830,16 +833,14 @@ var fh = 'firehose-' + el[1]; var wait_interval = 800; if(el[0] == "add") { - if (firehose_before[el[1]] && $('firehose-' + firehose_before[el[1]])) { - new Insertion.After('firehose-' + firehose_before[el[1]], el[2]); - - - } else if (firehose_after[el[1]] && $('firehose-' + firehose_after[el[1]])) { - new Insertion.Before('firehose-' + firehose_after[el[1]], el[2]); + if (firehose_before[el[1]] && jQuery('#firehose-' + firehose_before[el[1]]).size()) { + jQuery('#firehose-' + firehose_before[el[1]]).after(el[2]); + } else if (firehose_after[el[1]] && jQuery('#firehose-' + firehose_after[el[1]]).size()) { + jQuery('#firehose-' + firehose_after[el[1]]).before(el[2]); } else if (insert_new_at == "bottom") { - new Insertion.Bottom('firehoselist', el[2]); + jQuery('#firehoselist').append(el[2]); } else { - new Insertion.Top('firehoselist', el[2]); + jQuery('#firehoselist').prepend(el[2]); } var toheight = 50; @@ -871,8 +872,8 @@ } myAnim.onComplete.subscribe(function() { - if ($(fh)) { - $(fh).style.height = ""; + if ($dom(fh)) { + $dom(fh).style.height = ""; if (fh_use_jquery) { jQuery("#" + fh + " h3 a[class!='skin']").click( function(){ @@ -886,7 +887,7 @@ }); myAnim.animate(); } else if (el[0] == "remove") { - var fh_node = $(fh); + var fh_node = $dom(fh); if (fh_is_admin && fh_view_mode == "fulltitle" && fh_node && fh_node.className == "article" ) { // Don't delete admin looking at this in expanded view } else { @@ -919,7 +920,7 @@ }); myAnim.animate(); } else { - var elem = $(fh); + var elem = $dom(fh); wait_interval = 25; if (elem && elem.parentNode) { elem.parentNode.removeChild(elem); @@ -927,7 +928,7 @@ } } } - setTimeout("firehose_handle_update()", wait_interval); + setTimeout(firehose_handle_update, wait_interval); } else { firehose_reorder(); firehose_get_next_updates(); @@ -936,32 +937,28 @@ function firehose_reorder() { if (firehose_ordered) { - var fhlist = $('firehoselist'); + var fhlist = $dom('firehoselist'); if (fhlist) { var item_count = 0; for (i = 0; i < firehose_ordered.length; i++) { if (/^\d+$/.test(firehose_ordered[i])) { item_count++; } - var fhel = $('firehose-' + firehose_ordered[i]); + var fhel = $dom('firehose-' + firehose_ordered[i]); if (fhlist && fhel) { fhlist.appendChild(fhel); } if ( firehose_future[firehose_ordered[i]] ) { - if ($("ttype-" + firehose_ordered[i])) { - $("ttype-" + firehose_ordered[i]).className = "future"; + if ($dom("ttype-" + firehose_ordered[i])) { + $dom("ttype-" + firehose_ordered[i]).className = "future"; } } else { - if ($("ttype-" + firehose_ordered[i]) && $("ttype-" + firehose_ordered[i]).className == "future") { - $("ttype-" + firehose_ordered[i]).className = "story"; + if ($dom("ttype-" + firehose_ordered[i]) && $dom("ttype-" + firehose_ordered[i]).className == "future") { + $dom("ttype-" + firehose_ordered[i]).className = "story"; } } } - if (console_updating) { - document.title = sitename + " - Console (" + item_count + ")"; - } else { - document.title = sitename + " - Firehose (" + item_count + ")"; - } + document.title = "[% sitename %] - " + (console_updating ? "Console" : "Firehose") + " (" + item_count + ")"; } } @@ -971,13 +968,13 @@ var interval = getFirehoseUpdateInterval(); //alert("fh_get_next_updates"); fh_is_updating = 0; - firehose_add_update_timerid(setTimeout("firehose_get_updates()", interval)); + firehose_add_update_timerid(setTimeout(firehose_get_updates, interval)); } function firehose_get_updates_handler(transport) { - if ($('busy')) { - $('busy').className = "hide"; + if ($dom('busy')) { + $dom('busy').className = "hide"; } var response = eval_response(transport); var processed = 0; @@ -1008,7 +1005,7 @@ } function firehose_get_item_idstring() { - var fhl = $('firehoselist'); + var fhl = $dom('firehoselist'); var str = ""; var children; if (fhl) { @@ -1033,7 +1030,7 @@ options = options || {}; run_before_update(); if ((fh_play == 0 && !options.oneupdate) || fh_is_updating == 1) { - firehose_add_update_timerid(setTimeout("firehose_get_updates()", 2000)); + firehose_add_update_timerid(setTimeout(firehose_get_updates, 2000)); // alert("wait loop: " + fh_is_updating); return; } @@ -1042,7 +1039,7 @@ while(id = fh_update_timerids.pop()) { clearTimeout(id) }; } fh_is_updating = 1 - var params = []; + var params = {}; var handlers = { onComplete: firehose_get_updates_handler }; @@ -1058,8 +1055,8 @@ params['embed'] = 1; } params['fh_pageval'] = firehose_settings.pageval; - if ($('busy')) { - $('busy').className = ""; + if ($dom('busy')) { + $dom('busy').className = ""; } ajax_update(params, '', handlers); } @@ -1103,8 +1100,8 @@ var secs = getSecsSinceLastFirehoseAction(); if (secs > inactivity_timeout) { fh_is_timed_out = 1; - if ($('message_area')) - $('message_area').innerHTML = "Automatic updates have been slowed due to inactivity"; + if ($dom('message_area')) + $dom('message_area').innerHTML = "Automatic updates have been slowed due to inactivity"; //firehose_pause(); } } @@ -1113,15 +1110,15 @@ fh_play = 1; setFirehoseAction(); firehose_set_options('pause', '0'); - var pausepanel = $('pauseorplay'); - if ($('message_area')) - $('message_area').innerHTML = ""; + var pausepanel = $dom('pauseorplay'); + if ($dom('message_area')) + $dom('message_area').innerHTML = ""; if (pausepanel) { pausepanel.innerHTML = "Updated"; } - var pause = $('pause'); + var pause = $dom('pause'); - var play_div = $('play'); + var play_div = $dom('play'); if (play_div) { play_div.className = "hide"; } @@ -1130,14 +1127,18 @@ } } +function is_firehose_playing() { + return YAHOO.util.Dom.hasClass('play', 'hide'); +} + function firehose_pause() { fh_play = 0; - var pause = $('pause'); - var play_div = $('play'); + var pause = $dom('pause'); + var play_div = $dom('play'); pause.className = "hide"; play_div.className = "show"; - if ($('pauseorplay')) { - $('pauseorplay').innerHTML = "Paused"; + if ($dom('pauseorplay')) { + $dom('pauseorplay').innerHTML = "Paused"; } firehose_set_options('pause', '1'); } @@ -1147,8 +1148,8 @@ } function firehose_collapse_entry(id) { - var fhbody = $('fhbody-'+id); - var fh = $('firehose-'+id); + var fhbody = $dom('fhbody-'+id); + var fh = $dom('firehose-'+id); if (fhbody && fhbody.className == "body") { fhbody.className = "hide"; } @@ -1160,7 +1161,7 @@ } function firehose_remove_entry(id) { - var fh = $('firehose-' + id); + var fh = $dom('firehose-' + id); if (fh) { var attributes = { height: { to: 0 } @@ -1205,7 +1206,7 @@ fh_slider_init_set = 1; } var color = fh_colors[ newVal / fh_ticksize ]; - $('fh_slider_img').title = "Firehose filtered to " + color; + $dom('fh_slider_img').title = "Firehose filtered to " + color; if (fh_slider_init_set) { firehose_set_options("color", color) } @@ -1222,7 +1223,7 @@ function pausePopVendorStory(id) { vendor_popup_id=id; closePopup('vendorStory-26-popup'); - vendor_popup_timerids[id] = setTimeout("vendorStoryPopup()", 500); + vendor_popup_timerids[id] = setTimeout(vendorStoryPopup, 500); } function clearVendorPopupTimers() { @@ -1242,7 +1243,7 @@ } }; createPopup(getXYForId('sponsorlinks', 0, 0), title, "vendorStory-" + id, "Loading", "", closepopup ); - var params = []; + var params = {}; params['op'] = 'getTopVendorStory'; params['skid'] = id; ajax_update(params, "vendorStory-" + id + "-contents"); @@ -1251,7 +1252,7 @@ function pausePopVendorStory2(id) { vendor_popup_id=id; closePopup('vendorStory-26-popup'); - vendor_popup_timerids[id] = setTimeout("vendorStoryPopup2()", 500); + vendor_popup_timerids[id] = setTimeout(vendorStoryPopup2, 500); } function vendorStoryPopup2() { @@ -1267,14 +1268,14 @@ } }; createPopup(getXYForId('sponsorlinks2', 0, 0), title, "vendorStory-" + id, "Loading", "", closepopup ); - var params = []; + var params = {}; params['op'] = 'getTopVendorStory'; params['skid'] = id; ajax_update(params, "vendorStory-" + id + "-contents"); } function logToDiv(id, message) { - var div = $(id); + var div = $dom(id); if (div) { div.innerHTML = div.innerHTML + message + "<br>"; } @@ -1282,19 +1283,19 @@ function firehose_open_tab(id) { - var tf = $('tab-form-'+id); - var tt = $('tab-text-'+id); - var ti = $('tab-input-'+id); + var tf = $dom('tab-form-'+id); + var tt = $dom('tab-text-'+id); + var ti = $dom('tab-input-'+id); tf.className=""; ti.focus(); tt.className="hide"; } function firehose_save_tab(id) { - var tf = $('tab-form-'+id); - var tt = $('tab-text-'+id); - var ti = $('tab-input-'+id); - var params = []; + var tf = $dom('tab-form-'+id); + var tt = $dom('tab-text-'+id); + var ti = $dom('tab-input-'+id); + var params = {}; var handlers = { onComplete: json_handler }; @@ -1375,8 +1376,8 @@ var modal_inst = 0; function init_modal_divs() { - modal_cover = $('modal_cover'); - modal_box = $('modal_box'); + modal_cover = $dom('modal_cover'); + modal_box = $dom('modal_box'); } function install_modal() { @@ -1392,7 +1393,7 @@ modal_cover.parentNode.removeChild(modal_cover); modal_box.parentNode.removeChild(modal_box); - var modal_parent = $('top_parent'); + var modal_parent = $dom('top_parent'); modal_parent.parentNode.insertBefore(modal_cover, modal_parent); modal_parent.parentNode.insertBefore(modal_box, modal_parent); modal_inst = 1; @@ -1423,12 +1424,12 @@ } function getModalPrefs(section, title, tabbed) { - document.getElementById('preference_title').innerHTML = title; - var params = []; + document.getElementById('preference_title').innerHTML = title; + var params = {}; params['op'] = 'getModalPrefs'; params['section'] = section; params['reskey'] = reskey_static; - params['tabbed'] = tabbed; + params['tabbed'] = tabbed; var handlers = {onComplete:show_modal_box}; ajax_update(params, 'modal_box_content', handlers); @@ -1436,21 +1437,21 @@ } function firehose_get_media_popup(id) { - if ($('preference_title')) { - $('preference_title').innerHTML = "Media"; + if ($dom('preference_title')) { + $dom('preference_title').innerHTML = "Media"; } - var params = []; + var params = {}; params['op'] = 'firehose_get_media'; params['id'] = id; show_modal_box(); - $('modal_box_content').innerHTML = "<h4>Loading...</h4><img src='/images/spinner_large.gif'>"; + $dom('modal_box_content').innerHTML = "<h4>Loading...</h4><img src='/images/spinner_large.gif'>"; ajax_update(params, 'modal_box_content'); } function saveModalPrefs() { - var params = []; + var params = {}; params['op'] = 'saveModalPrefs'; - params['data'] = Form.serialize(document.forms['modal_prefs']); + params['data'] = jQuery("#modal_prefs").serialize(); params['reskey'] = reskey_static; var handlers = { onComplete: function() { @@ -1473,7 +1474,7 @@ sep = ","; } - var params = []; + var params = {}; params['op'] = 'page_save_user_boxes'; params['reskey'] = reskey_static; params['bids'] = all; @@ -1496,14 +1497,14 @@ } function toggle_filter_prefs() { - var fps = $('filter_play_status'); - var fp = $('filter_prefs'); + var fps = $dom('filter_play_status'); + var fp = $dom('filter_prefs'); if (fps) { if (fps.className == "") { fps.className = "hide"; if (fp) { fp.className = ""; - setTimeout("firehose_slider_init()",500); + setTimeout(firehose_slider_init,500); } } else if (fps.className == "hide") { fps.className = ""; @@ -1514,3 +1515,126 @@ } } + +function admin_signoff(stoid, type, id) { + var params = []; + params['op'] = 'admin_signoff'; + params['stoid'] = stoid; + params['reskey'] = reskey_static; + ajax_update(params, 'signoff_' + stoid); + if (type == "firehose") { + firehose_collapse_entry(id); + } +} + + +function scrollWindowToFirehose(fhid) { + var firehose_y = getOffsetTop($('firehose-' + fhid)); + console.log(firehose_y); + scroll(viewWindowLeft(), firehose_y); +} + +function viewWindowLeft() { + if (self.pageXOffset) // all except Explorer + { + return self.pageXOffset; + } + else if (document.documentElement && document.documentElement.scrollTop) + // Explorer 6 Strict + { + return document.documentElement.scrollLeft; + } + else if (document.body) // all other Explorers + { + return document.body.scrollLeft; + } +} + +function getOffsetTop (el) { + if (!el) + return false; + var ot = el.offsetTop; + while((el = el.offsetParent) != null) + ot += el.offsetTop; + return ot; +} + +function firehoseIsInWindow(fhid, just_head) { + var in_window = isInWindow($('firehose-' + fhid)); + return in_window; +} + +function isInWindow(obj) { + var y = getOffsetTop(obj); + + if (y > viewWindowTop() && y < viewWindowBottom()) { + return 1; + } + return 0; +} + +function viewWindowTop() { + if (self.pageYOffset) // all except Explorer + { + return self.pageYOffset; + } + else if (document.documentElement && document.documentElement.scrollTop) + // Explorer 6 Strict + { + return document.documentElement.scrollTop; + } + else if (document.body) // all other Explorers + { + return document.body.scrollTop; + } + return; +} + +function viewWindowBottom() { + return viewWindowTop() + (window.innerHeight || document.documentElement.clientHeight); +} + +function firehose_get_cur() { + if (!firehose_cur) { + firehose_cur = firehose_ordered[0]; + firehose_set_cur(firehose_cur); + } + return firehose_cur; +} + +function firehose_set_cur(id) { + firehose_cur = id; +} + +function firehose_get_pos_of_id(id) { + var ret; + for (var i=0; i< firehose_ordered.length; i++) { + if (firehose_ordered[i] == id) { + ret = i; + } + } + return ret; +} + +function firehose_go_next() { + var cur = firehose_get_cur(); + var pos = firehose_get_pos_of_id(cur); + if (pos < (firehose_ordered.length - 1)) { + pos++; + } + firehose_set_cur(firehose_ordered[pos]); + scrollWindowToFirehose(firehose_cur); +} + +function firehose_go_prev() { + var cur = firehose_get_cur(); + var pos = firehose_get_pos_of_id(cur); + if (pos>0) { + pos--; + } + firehose_set_cur(firehose_ordered[pos]); + scrollWindowToFirehose(firehose_cur); + +} + + Added: slashjp/branches/upstream/current/plugins/Ajax/htdocs/images/jquery-1.2.3.js =================================================================== --- slashjp/branches/upstream/current/plugins/Ajax/htdocs/images/jquery-1.2.3.js (rev 0) +++ slashjp/branches/upstream/current/plugins/Ajax/htdocs/images/jquery-1.2.3.js 2008-04-01 03:35:14 UTC (rev 560) @@ -0,0 +1,11 @@ +/* + * jQuery 1.2.3 - New Wave Javascript + * + * Copyright (c) 2008 John Resig (jquery.com) + * Dual licensed under the MIT (MIT-LICENSE.txt) + * and GPL (GPL-LICENSE.txt) licenses. + * + * $Date: 2008/03/14 15:48:06 $ + * $Rev: 4663 $ + */ +eval(function(p,a,c,k,e,r){e=function(c){return(c<a?'':e(parseInt(c/a)))+((c=c%a)>35?String.fromCharCode(c+29):c.toString(36))};if(!''.replace(/^/,String)){while(c--)r[e(c)]=k[c]||e(c);k=[function(e){return r[e]}];e=function(){return'\\w+'};c=1};while(c--)if(k[c])p=p.replace(new RegExp('\\b'+e(c)+'\\b','g'),k[c]);return p}('(J(){7(1e.3N)L w=1e.3N;L E=1e.3N=J(a,b){K 1B E.2l.4T(a,b)};7(1e.$)L D=1e.$;1e.$=E;L u=/^[^<]*(<(.|\\s)+>)[^>]*$|^#(\\w+)$/;L G=/^.[^:#\\[\\.]*$/;E.1n=E.2l={4T:J(d,b){d=d||T;7(d.15){6[0]=d;6.M=1;K 6}N 7(1o d=="25"){L c=u.2O(d);7(c&&(c[1]||!b)){7(c[1])d=E.4a([c[1]],b);N{L a=T.5J(c[3]);7(a)7(a.2w!=c[3])K E().2s(d);N{6[0]=a;6.M=1;K 6}N d=[]}}N K 1B E(b).2s(d)}N 7(E.1q(d))K 1B E(T)[E.1n.21?"21":"3U"](d);K 6.6E(d.1k==1M&&d||(d.5h||d.M&&d!=1e&&!d.15&&d[0]!=10&&d[0].15)&&E.2I(d)||[d])},5h:"1.2.3",87:J(){K 6.M},M:0,22:J(a){K a==10?E.2I(6):6[a]},2F:J(b){L a=E(b);a.54=6;K a},6E:J(a){6.M=0;1M.2l.1g.1i(6,a);K 6},R:J(a,b){K E.R(6,a,b)},4X:J(b){L a=-1;6.R(J(i){7(6==b)a=i});K a},1J:J(c,a,b){L d=c;7(c.1k==4e)7(a==10)K 6.M&&E[b||"1J"](6[0],c)||10;N{d={};d[c]=a}K 6.R(J(i){Q(c 1p d)E.1J(b?6.W:6,c,E.1l(6,d[c],b,i,c))})},1j:J(b,a){7((b==\'27\'||b==\'1R\')&&2M(a)<0)a=10;K 6.1J(b,a,"2o")},1u:J(b){7(1o b!="3V"&&b!=V)K 6.4x().3t((6[0]&&6[0].2i||T).5r(b));L a="";E.R(b||6,J(){E.R(6.3p,J(){7(6.15!=8)a+=6.15!=1?6.6K:E.1n.1u([6])})});K a},5m:J(b){7(6[0])E(b,6[0].2i).5k().3o(6[0]).2c(J(){L a=6;2b(a.1C)a=a.1C;K a}).3t(6);K 6},8w:J(a){K 6.R(J(){E(6).6z().5m(a)})},8p:J(a){K 6.R(J(){E(6).5m(a)})},3t:J(){K 6.3O(18,P,S,J(a){7(6.15==1)6.38(a)})},6q:J(){K 6.3O(18,P,P,J(a){7(6.15==1)6.3o(a,6.1C)})},6o:J(){K 6.3O(18,S,S,J(a){6.1a.3o(a,6)})},5a:J(){K 6.3O(18,S,P,J(a){6.1a.3o(a,6.2B)})},3h:J(){K 6.54||E([])},2s:J(b){L c=E.2c(6,J(a){K E.2s(b,a)});K 6.2F(/[^+>] [^+>]/.17(b)||b.1f("..")>-1?E.57(c):c)},5k:J(e){L f=6.2c(J(){7(E.14.1d&&!E.3E(6)){L a=6.69(P),4Y=T.3s("1x");4Y.38(a);K E.4a([4Y.3d])[0]}N K 6.69(P)});L d=f.2s("*").4R().R(J(){7(6[F]!=10)6[F]=V});7(e===P)6.2s("*").4R().R(J(i){7(6.15==3)K;L c=E.O(6,"2R");Q(L a 1p c)Q(L b 1p c[a])E.16.1b(d[i],a,c[a][b],c[a][b].O)});K f},1E:J(b){K 6.2F(E.1q(b)&&E.3y(6,J(a,i){K b.1P(a,i)})||E.3e(b,6))},56:J(b){7(b.1k==4e)7(G.17(b))K 6.2F(E.3e(b,6,P));N b=E.3e(b,6);L a=b.M&&b[b.M-1]!==10&&!b.15;K 6.1E(J(){K a?E.33(6,b)<0:6!=b})},1b:J(a){K!a?6:6.2F(E.37(6.22(),a.1k==4e?E(a).22():a.M!=10&&(!a.12||E.12(a,"3u"))?a:[a]))},3H:J(a){K a?E.3e(a,6).M>0:S},7j:J(a){K 6.3H("."+a)},5O:J(b){7(b==10){7(6.M){L c=6[0];7(E.12(c,"2k")){L e=c.3T,5I=[],11=c.11,2X=c.U=="2k-2X";7(e<0)K V;Q(L i=2X?e:0,2f=2X?e+1:11.M;i<2f;i++){L d=11[i];7(d.2p){b=E.14.1d&&!d.9J.1A.9y?d.1u:d.1A;7(2X)K b;5I.1g(b)}}K 5I}N K(6[0].1A||"").1r(/\\r/g,"")}K 10}K 6.R(J(){7(6.15!=1)K;7(b.1k==1M&&/5u|5t/.17(6.U))6.3k=(E.33(6.1A,b)>=0||E.33(6.31,b)>=0);N 7(E.12(6,"2k")){L a=b.1k==1M?b:[b];E("98",6).R(J(){6.2p=(E.33(6.1A,a)>=0||E.33(6.1u,a)>=0)});7(!a.M)6.3T=-1}N 6.1A=b})},3q:J(a){K a==10?(6.M?6[0].3d:V):6.4x().3t(a)},6S:J(a){K 6.5a(a).1V()},6Z:J(i){K 6.2K(i,i+1)},2K:J(){K 6.2F(1M.2l.2K.1i(6,18))},2c:J(b){K 6.2F(E.2c(6,J(a,i){K b.1P(a,i,a)}))},4R:J(){K 6.1b(6.54)},O:J(d,b){L a=d.23(".");a[1]=a[1]?"."+a[1]:"";7(b==V){L c=6.5n("8P"+a[1]+"!",[a[0]]);7(c==10&&6.M)c=E.O(6[0],d);K c==V&&a[1]?6.O(a[0]):c}N K 6.1N("8K"+a[1]+"!",[a[0],b]).R(J(){E.O(6,d,b)})},35:J(a){K 6.R(J(){E.35(6,a)})},3O:J(g,f,h,d){L e=6.M>1,3n;K 6.R(J(){7(!3n){3n=E.4a(g,6.2i);7(h)3n.8D()}L b=6;7(f&&E.12(6,"1O")&&E.12(3n[0],"4v"))b=6.3S("1U")[0]||6.38(6.2i.3s("1U"));L c=E([]);E.R(3n,J(){L a=e?E(6).5k(P)[0]:6;7(E.12(a,"1m")){c=c.1b(a)}N{7(a.15==1)c=c.1b(E("1m",a).1V());d.1P(b,a)}});c.R(6A)})}};E.2l.4T.2l=E.2l;J 6A(i,a){7(a.3Q)E.3P({1c:a.3Q,3l:S,1H:"1m"});N E.5g(a.1u||a.6x||a.3d||"");7(a.1a)a.1a.34(a)}E.1s=E.1n.1s=J(){L b=18[0]||{},i=1,M=18.M,5c=S,11;7(b.1k==8d){5c=b;b=18[1]||{};i=2}7(1o b!="3V"&&1o b!="J")b={};7(M==1){b=6;i=0}Q(;i<M;i++)7((11=18[i])!=V)Q(L a 1p 11){7(b===11[a])6w;7(5c&&11[a]&&1o 11[a]=="3V"&&b[a]&&!11[a].15)b[a]=E.1s(b[a],11[a]);N 7(11[a]!=10)b[a]=11[a]}K b};L F="3N"+(1B 3v()).3L(),6t=0,5b={};L H=/z-?4X|86-?84|1w|6k|7Z-?1R/i;E.1s({7Y:J(a){1e.$=D;7(a)1e.3N=w;K E},1q:J(a){K!!a&&1o a!="25"&&!a.12&&a.1k!=1M&&/J/i.17(a+"")},3E:J(a){K a.1F&&!a.1h||a.28&&a.2i&&!a.2i.1h},5g:J(a){a=E.3g(a);7(a){L b=T.3S("6f")[0]||T.1F,1m=T.3s("1m");1m.U="1u/4m";7(E.14.1d)1m.1u=a;N 1m.38(T.5r(a));b.38(1m);b.34(1m)}},12:J(b,a){K b.12&&b.12.2E()==a.2E()},1T:{},O:J(c,d,b){c=c==1e?5b:c;L a=c[F];7(!a)a=c[F]=++6t;7(d&&!E.1T[a])E.1T[a]={};7(b!=10)E.1T[a][d]=b;K d?E.1T[a][d]:a},35:J(c,b){c=c==1e?5b:c;L a=c[F];7(b){7(E.1T[a]){2V E.1T[a][b];b="";Q(b 1p E.1T[a])1Q;7(!b)E.35(c)}}N{1S{2V c[F]}1X(e){7(c.52)c.52(F)}2V E.1T[a]}},R:J(c,a,b){7(b){7(c.M==10){Q(L d 1p c)7(a.1i(c[d],b)===S)1Q}N Q(L i=0,M=c.M;i<M;i++)7(a.1i(c[i],b)===S)1Q}N{7(c.M==10){Q(L d 1p c)7(a.1P(c[d],d,c[d])===S)1Q}N Q(L i=0,M=c.M,1A=c[0];i<M&&a.1P(1A,i,1A)!==S;1A=c[++i]){}}K c},1l:J(b,a,c,i,d){7(E.1q(a))a=a.1P(b,i);K a&&a.1k==51&&c=="2o"&&!H.17(d)?a+"2S":a},1t:{1b:J(c,b){E.R((b||"").23(/\\s+/),J(i,a){7(c.15==1&&!E.1t.3Y(c.1t,a))c.1t+=(c.1t?" ":"")+a})},1V:J(c,b){7(c.15==1)c.1t=b!=10?E.3y(c.1t.23(/\\s+/),J(a){K!E.1t.3Y(b,a)}).6a(" "):""},3Y:J(b,a){K E.33(a,(b.1t||b).3X().23(/\\s+/))>-1}},68:J(b,c,a){L e={};Q(L d 1p c){e[d]=b.W[d];b.W[d]=c[d]}a.1P(b);Q(L d 1p c)b.W[d]=e[d]},1j:J(d,e,c){7(e=="27"||e=="1R"){L b,46={43:"4W",4U:"1Z",19:"3D"},3c=e=="27"?["7O","7M"]:["7J","7I"];J 5E(){b=e=="27"?d.7H:d.7F;L a=0,2N=0;E.R(3c,J(){a+=2M(E.2o(d,"7E"+6,P))||0;2N+=2M(E.2o(d,"2N"+6+"5X",P))||0});b-=24.7C(a+2N)}7(E(d).3H(":4d"))5E();N E.68(d,46,5E);K 24.2f(0,b)}K E.2o(d,e,c)},2o:J(e,k,j){L d;J 3x(b){7(!E.14.2d)K S;L a=T.4c.4K(b,V);K!a||a.4M("3x")==""}7(k=="1w"&&E.14.1d){d=E.1J(e.W,"1w");K d==""?"1":d}7(E.14.2z&&k=="19"){L c=e.W.50;e.W.50="0 7r 7o";e.W.50=c}7(k.1D(/4g/i))k=y;7(!j&&e.W&&e.W[k])d=e.W[k];N 7(T.4c&&T.4c.4K){7(k.1D(/4g/i))k="4g";k=k.1r(/([A-Z])/g,"-$1").2h();L h=T.4c.4K(e,V);7(h&&!3x(e))d=h.4M(k);N{L f=[],2C=[];Q(L a=e;a&&3x(a);a=a.1a)2C.4J(a);Q(L i=0;i<2C.M;i++)7(3x(2C[i])){f[i]=2C[i].W.19;2C[i].W.19="3D"}d=k=="19"&&f[2C.M-1]!=V?"2H":(h&&h.4M(k))||"";Q(L i=0;i<f.M;i++)7(f[i]!=V)2C[i].W.19=f[i]}7(k=="1w"&&d=="")d="1"}N 7(e.4n){L g=k.1r(/\\-(\\w)/g,J(a,b){K b.2E()});d=e.4n[k]||e.4n[g];7(!/^\\d+(2S)?$/i.17(d)&&/^\\d/.17(d)){L l=e.W.26,3K=e.3K.26;e.3K.26=e.4n.26;e.W.26=d||0;d=e.W.7f+"2S";e.W.26=l;e.3K.26=3K}}K d},4a:J(l,h){L k=[];h=h||T;7(1o h.3s==\'10\')h=h.2i||h[0]&&h[0].2i||T;E.R(l,J(i,d){7(!d)K;7(d.1k==51)d=d.3X();7(1o d=="25"){d=d.1r(/(<(\\w+)[^>]*?)\\/>/g,J(b,a,c){K c.1D(/^(aa|a6|7e|a5|4D|7a|a0|3m|9W|9U|9S)$/i)?b:a+"></"+c+">"});L f=E.3g(d).2h(),1x=h.3s("1x");L e=!f.1f("<9P")&&[1,"<2k 74=\'74\'>","</2k>"]||!f.1f("<9M")&&[1,"<73>","</73>"]||f.1D(/^<(9G|1U|9E|9B|9x)/)&&[1,"<1O>","</1O>"]||!f.1f("<4v")&&[2,"<1O><1U>","</1U></1O>"]||(!f.1f("<9w")||!f.1f("<9v"))&&[3,"<1O><1U><4v>","</4v></1U></1O>"]||!f.1f("<7e")&&[2,"<1O><1U></1U><6V>","</6V></1O>"]||E.14.1d&&[1,"1x<1x>","</1x>"]||[0,"",""];1x.3d=e[1]+d+e[2];2b(e[0]--)1x=1x.5o;7(E.14.1d){L g=!f.1f("<1O")&&f.1f("<1U")<0?1x.1C&&1x.1C.3p:e[1]=="<1O>"&&f.1f("<1U")<0?1x.3p:[];Q(L j=g.M-1;j>=0;--j)7(E.12(g[j],"1U")&&!g[j].3p.M)g[j].1a.34(g[j]);7(/^\\s/.17(d))1x.3o(h.5r(d.1D(/^\\s*/)[0]),1x.1C)}d=E.2I(1x.3p)}7(d.M===0&&(!E.12(d,"3u")&&!E.12(d,"2k")))K;7(d[0]==10||E.12(d,"3u")||d.11)k.1g(d);N k=E.37(k,d)});K k},1J:J(d,e,c){7(!d||d.15==3||d.15==8)K 10;L f=E.3E(d)?{}:E.46;7(e=="2p"&&E.14.2d)d.1a.3T;7(f[e]){7(c!=10)d[f[e]]=c;K d[f[e]]}N 7(E.14.1d&&e=="W")K E.1J(d.W,"9u",c);N 7(c==10&&E.14.1d&&E.12(d,"3u")&&(e=="9r"||e=="9o"))K d.9m(e).6K;N 7(d.28){7(c!=10){7(e=="U"&&E.12(d,"4D")&&d.1a)6Q"U 9i 9h\'t 9g 9e";d.9b(e,""+c)}7(E.14.1d&&/6O|3Q/.17(e)&&!E.3E(d))K d.4z(e,2);K d.4z(e)}N{7(e=="1w"&&E.14.1d){7(c!=10){d.6k=1;d.1E=(d.1E||"").1r(/6M\\([^)]*\\)/,"")+(2M(c).3X()=="96"?"":"6M(1w="+c*6L+")")}K d.1E&&d.1E.1f("1w=")>=0?(2M(d.1E.1D(/1w=([^)]*)/)[1])/6L).3X():""}e=e.1r(/-([a-z])/95,J(a,b){K b.2E()});7(c!=10)d[e]=c;K d[e]}},3g:J(a){K(a||"").1r(/^\\s+|\\s+$/g,"")},2I:J(b){L a=[];7(1o b!="93")Q(L i=0,M=b.M;i<M;i++)a.1g(b[i]);N a=b.2K(0);K a},33:J(b,a){Q(L i=0,M=a.M;i<M;i++)7(a[i]==b)K i;K-1},37:J(a,b){7(E.14.1d){Q(L i=0;b[i];i++)7(b[i].15!=8)a.1g(b[i])}N Q(L i=0;b[i];i++)a.1g(b[i]);K a},57:J(a){L c=[],2r={};1S{Q(L i=0,M=a.M;i<M;i++){L b=E.O(a[i]);7(!2r[b]){2r[b]=P;c.1g(a[i])}}}1X(e){c=a}K c},3y:J(c,a,d){L b=[];Q(L i=0,M=c.M;i<M;i++)7(!d&&a(c[i],i)||d&&!a(c[i],i))b.1g(c[i]);K b},2c:J(d,a){L c=[];Q(L i=0,M=d.M;i<M;i++){L b=a(d[i],i);7(b!==V&&b!=10){7(b.1k!=1M)b=[b];c=c.71(b)}}K c}});L v=8Y.8W.2h();E.14={5K:(v.1D(/.+(?:8T|8S|8R|8O)[\\/: ]([\\d.]+)/)||[])[1],2d:/77/.17(v),2z:/2z/.17(v),1d:/1d/.17(v)&&!/2z/.17(v),48:/48/.17(v)&&!/(8L|77)/.17(v)};L y=E.14.1d?"6H":"75";E.1s({8I:!E.14.1d||T.6F=="79",46:{"Q":"8F","8E":"1t","4g":y,75:y,6H:y,3d:"3d",1t:"1t",1A:"1A",2Y:"2Y",3k:"3k",8C:"8B",2p:"2p",8A:"8z",3T:"3T",6C:"6C",28:"28",12:"12"}});E.R({6B:J(a){K a.1a},8y:J(a){K E.4u(a,"1a")},8x:J(a){K E.2Z(a,2,"2B")},8v:J(a){K E.2Z(a,2,"4t")},8u:J(a){K E.4u(a,"2B")},8t:J(a){K E.4u(a,"4t")},8s:J(a){K E.5i(a.1a.1C,a)},8r:J(a){K E.5i(a.1C)},6z:J(a){K E.12(a,"8q")?a.8o||a.8n.T:E.2I(a.3p)}},J(c,d){E.1n[c]=J(b){L a=E.2c(6,d);7(b&&1o b=="25")a=E.3e(b,a);K 6.2F(E.57(a))}});E.R({6y:"3t",8m:"6q",3o:"6o",8l:"5a",8k:"6S"},J(c,b){E.1n[c]=J(){L a=18;K 6.R(J(){Q(L i=0,M=a.M;i<M;i++)E(a[i])[b](6)})}});E.R({8j:J(a){E.1J(6,a,"");7(6.15==1)6.52(a)},8i:J(a){E.1t.1b(6,a)},8h:J(a){E.1t.1V(6,a)},8g:J(a){E.1t[E.1t.3Y(6,a)?"1V":"1b"](6,a)},1V:J(a){7(!a||E.1E(a,[6]).r.M){E("*",6).1b(6).R(J(){E.16.1V(6);E.35(6)});7(6.1a)6.1a.34(6)}},4x:J(){E(">*",6).1V();2b(6.1C)6.34(6.1C)}},J(a,b){E.1n[a]=J(){K 6.R(b,18)}});E.R(["8f","5X"],J(i,c){L b=c.2h();E.1n[b]=J(a){K 6[0]==1e?E.14.2z&&T.1h["5e"+c]||E.14.2d&&1e["8e"+c]||T.6F=="79"&&T.1F["5e"+c]||T.1h["5e"+c]:6[0]==T?24.2f(24.2f(T.1h["5d"+c],T.1F["5d"+c]),24.2f(T.1h["5L"+c],T.1F["5L"+c])):a==10?(6.M?E.1j(6[0],b):V):6.1j(b,a.1k==4e?a:a+"2S")}});L C=E.14.2d&&4s(E.14.5K)<8c?"(?:[\\\\w*4r-]|\\\\\\\\.)":"(?:[\\\\w\\8b-\\8a*4r-]|\\\\\\\\.)",6v=1B 4q("^>\\\\s*("+C+"+)"),6u=1B 4q("^("+C+"+)(#)("+C+"+)"),6s=1B 4q("^([#.]?)("+C+"*)");E.1s({6r:{"":J(a,i,m){K m[2]=="*"||E.12(a,m[2])},"#":J(a,i,m){K a.4z("2w")==m[2]},":":{89:J(a,i,m){K i<m[3]-0},88:J(a,i,m){K i>m[3]-0},2Z:J(a,i,m){K m[3]-0==i},6Z:J(a,i,m){K m[3]-0==i},3j:J(a,i){K i==0},3J:J(a,i,m,r){K i==r.M-1},6n:J(a,i){K i%2==0},6l:J(a,i){K i%2},"3j-4p":J(a){K a.1a.3S("*")[0]==a},"3J-4p":J(a){K E.2Z(a.1a.5o,1,"4t")==a},"83-4p":J(a){K!E.2Z(a.1a.5o,2,"4t")},6B:J(a){K a.1C},4x:J(a){K!a.1C},82:J(a,i,m){K(a.6x||a.81||E(a).1u()||"").1f(m[3])>=0},4d:J(a){K"1Z"!=a.U&&E.1j(a,"19")!="2H"&&E.1j(a,"4U")!="1Z"},1Z:J(a){K"1Z"==a.U||E.1j(a,"19")=="2H"||E.1j(a,"4U")=="1Z"},80:J(a){K!a.2Y},2Y:J(a){K a.2Y},3k:J(a){K a.3k},2p:J(a){K a.2p||E.1J(a,"2p")},1u:J(a){K"1u"==a.U},5u:J(a){K"5u"==a.U},5t:J(a){K"5t"==a.U},59:J(a){K"59"==a.U},3I:J(a){K"3I"==a.U},58:J(a){K"58"==a.U},6j:J(a){K"6j"==a.U},6i:J(a){K"6i"==a.U},2G:J(a){K"2G"==a.U||E.12(a,"2G")},4D:J(a){K/4D|2k|6h|2G/i.17(a.12)},3Y:J(a,i,m){K E.2s(m[3],a).M},7X:J(a){K/h\\d/i.17(a.12)},7W:J(a){K E.3y(E.3G,J(b){K a==b.Y}).M}}},6g:[/^(\\[) *@?([\\w-]+) *([!*$^~=]*) *(\'?"?)(.*?)\\4 *\\]/,/^(:)([\\w-]+)\\("?\'?(.*?(\\(.*?\\))?[^(]*?)"?\'?\\)/,1B 4q("^([:.#]*)("+C+"+)")],3e:J(a,c,b){L d,2m=[];2b(a&&a!=d){d=a;L f=E.1E(a,c,b);a=f.t.1r(/^\\s*,\\s*/,"");2m=b?c=f.r:E.37(2m,f.r)}K 2m},2s:J(t,p){7(1o t!="25")K[t];7(p&&p.15!=1&&p.15!=9)K[];p=p||T;L d=[p],2r=[],3J,12;2b(t&&3J!=t){L r=[];3J=t;t=E.3g(t);L o=S;L g=6v;L m=g.2O(t);7(m){12=m[1].2E();Q(L i=0;d[i];i++)Q(L c=d[i].1C;c;c=c.2B)7(c.15==1&&(12=="*"||c.12.2E()==12))r.1g(c);d=r;t=t.1r(g,"");7(t.1f(" ")==0)6w;o=P}N{g=/^([>+~])\\s*(\\w*)/i;7((m=g.2O(t))!=V){r=[];L l={};12=m[2].2E();m=m[1];Q(L j=0,3f=d.M;j<3f;j++){L n=m=="~"||m=="+"?d[j].2B:d[j].1C;Q(;n;n=n.2B)7(n.15==1){L h=E.O(n);7(m=="~"&&l[h])1Q;7(!12||n.12.2E()==12){7(m=="~")l[h]=P;r.1g(n)}7(m=="+")1Q}}d=r;t=E.3g(t.1r(g,""));o=P}}7(t&&!o){7(!t.1f(",")){7(p==d[0])d.4l();2r=E.37(2r,d);r=d=[p];t=" "+t.6e(1,t.M)}N{L k=6u;L m=k.2O(t);7(m){m=[0,m[2],m[3],m[1]]}N{k=6s;m=k.2O(t)}m[2]=m[2].1r(/\\\\/g,"");L f=d[d.M-1];7(m[1]=="#"&&f&&f.5J&&!E.3E(f)){L q=f.5J(m[2]);7((E.14.1d||E.14.2z)&&q&&1o q.2w=="25"&&q.2w!=m[2])q=E(\'[@2w="\'+m[2]+\'"]\',f)[0];d=r=q&&(!m[3]||E.12(q,m[3]))?[q]:[]}N{Q(L i=0;d[i];i++){L a=m[1]=="#"&&m[3]?m[3]:m[1]!=""||m[0]==""?"*":m[2];7(a=="*"&&d[i].12.2h()=="3V")a="3m";r=E.37(r,d[i].3S(a))}7(m[1]==".")r=E.55(r,m[2]);7(m[1]=="#"){L e=[];Q(L i=0;r[i];i++)7(r[i].4z("2w")==m[2]){e=[r[i]];1Q}r=e}d=r}t=t.1r(k,"")}}7(t){L b=E.1E(t,r);d=r=b.r;t=E.3g(b.t)}}7(t)d=[];7(d&&p==d[0])d.4l();2r=E.37(2r,d);K 2r},55:J(r,m,a){m=" "+m+" ";L c=[];Q(L i=0;r[i];i++){L b=(" "+r[i].1t+" ").1f(m)>=0;7(!a&&b||a&&!b)c.1g(r[i])}K c},1E:J(t,r,h){L d;2b(t&&t!=d){d=t;L p=E.6g,m;Q(L i=0;p[i];i++){m=p[i].2O(t);7(m){t=t.7V(m[0].M);m[2]=m[2].1r(/\\\\/g,"");1Q}}7(!m)1Q;7(m[1]==":"&&m[2]=="56")r=G.17(m[3])?E.1E(m[3],r,P).r:E(r).56(m[3]);N 7(m[1]==".")r=E.55(r,m[2],h);N 7(m[1]=="["){L g=[],U=m[3];Q(L i=0,3f=r.M;i<3f;i++){L a=r[i],z=a[E.46[m[2]]||m[2]];7(z==V||/6O|3Q|2p/.17(m[2]))z=E.1J(a,m[2])||\'\';7((U==""&&!!z||U=="="&&z==m[5]||U=="!="&&z!=m[5]||U=="^="&&z&&!z.1f(m[5])||U=="$="&&z.6e(z.M-m[5].M)==m[5]||(U=="*="||U=="~=")&&z.1f(m[5])>=0)^h)g.1g(a)}r=g}N 7(m[1]==":"&&m[2]=="2Z-4p"){L e={},g=[],17=/(-?)(\\d*)n((?:\\+|-)?\\d*)/.2O(m[3]=="6n"&&"2n"||m[3]=="6l"&&"2n+1"||!/\\D/.17(m[3])&&"7U+"+m[3]||m[3]),3j=(17[1]+(17[2]||1))-0,d=17[3]-0;Q(L i=0,3f=r.M;i<3f;i++){L j=r[i],1a=j.1a,2w=E.O(1a);7(!e[2w]){L c=1;Q(L n=1a.1C;n;n=n.2B)7(n.15==1)n.4k=c++;e[2w]=P}L b=S;7(3j==0){7(j.4k==d)b=P}N 7((j.4k-d)%3j==0&&(j.4k-d)/3j>=0)b=P;7(b^h)g.1g(j)}r=g}N{L f=E.6r[m[1]];7(1o f=="3V")f=f[m[2]];7(1o f=="25")f=6c("S||J(a,i){K "+f+";}");r=E.3y(r,J(a,i){K f(a,i,m,r)},h)}}K{r:r,t:t}},4u:J(b,c){L d=[];L a=b[c];2b(a&&a!=T){7(a.15==1)d.1g(a);a=a[c]}K d},2Z:J(a,e,c,b){e=e||1;L d=0;Q(;a;a=a[c])7(a.15==1&&++d==e)1Q;K a},5i:J(n,a){L r=[];Q(;n;n=n.2B){7(n.15==1&&(!a||n!=a))r.1g(n)}K r}});E.16={1b:J(f,i,g,e){7(f.15==3||f.15==8)K;7(E.14.1d&&f.53!=10)f=1e;7(!g.2D)g.2D=6.2D++;7(e!=10){L h=g;g=J(){K h.1i(6,18)};g.O=e;g.2D=h.2D}L j=E.O(f,"2R")||E.O(f,"2R",{}),1v=E.O(f,"1v")||E.O(f,"1v",J(){L a;7(1o E=="10"||E.16.5f)K a;a=E.16.1v.1i(18.3R.Y,18);K a});1v.Y=f;E.R(i.23(/\\s+/),J(c,b){L a=b.23(".");b=a[0];g.U=a[1];L d=j[b];7(!d){d=j[b]={};7(!E.16.2y[b]||E.16.2y[b].4j.1P(f)===S){7(f.3F)f.3F(b,1v,S);N 7(f.6b)f.6b("4i"+b,1v)}}d[g.2D]=g;E.16.2a[b]=P});f=V},2D:1,2a:{},1V:J(e,h,f){7(e.15==3||e.15==8)K;L i=E.O(e,"2R"),29,4X;7(i){7(h==10||(1o h=="25"&&h.7T(0)=="."))Q(L g 1p i)6.1V(e,g+(h||""));N{7(h.U){f=h.2q;h=h.U}E.R(h.23(/\\s+/),J(b,a){L c=a.23(".");a=c[0];7(i[a]){7(f)2V i[a][f.2D];N Q(f 1p i[a])7(!c[1]||i[a][f].U==c[1])2V i[a][f];Q(29 1p i[a])1Q;7(!29){7(!E.16.2y[a]||E.16.2y[a].4h.1P(e)===S){7(e.67)e.67(a,E.O(e,"1v"),S);N 7(e.66)e.66("4i"+a,E.O(e,"1v"))}29=V;2V i[a]}}})}Q(29 1p i)1Q;7(!29){L d=E.O(e,"1v");7(d)d.Y=V;E.35(e,"2R");E.35(e,"1v")}}},1N:J(g,c,d,f,h){c=E.2I(c||[]);7(g.1f("!")>=0){g=g.2K(0,-1);L a=P}7(!d){7(6.2a[g])E("*").1b([1e,T]).1N(g,c)}N{7(d.15==3||d.15==8)K 10;L b,29,1n=E.1q(d[g]||V),16=!c[0]||!c[0].36;7(16)c.4J(6.4Z({U:g,2L:d}));c[0].U=g;7(a)c[0].65=P;7(E.1q(E.O(d,"1v")))b=E.O(d,"1v").1i(d,c);7(!1n&&d["4i"+g]&&d["4i"+g].1i(d,c)===S)b=S;7(16)c.4l();7(h&&E.1q(h)){29=h.1i(d,b==V?c:c.71(b));7(29!==10)b=29}7(1n&&f!==S&&b!==S&&!(E.12(d,\'a\')&&g=="4V")){6.5f=P;1S{d[g]()}1X(e){}}6.5f=S}K b},1v:J(c){L a;c=E.16.4Z(c||1e.16||{});L b=c.U.23(".");c.U=b[0];L f=E.O(6,"2R")&&E.O(6,"2R")[c.U],42=1M.2l.2K.1P(18,1);42.4J(c);Q(L j 1p f){L d=f[j];42[0].2q=d;42[0].O=d.O;7(!b[1]&&!c.65||d.U==b[1]){L e=d.1i(6,42);7(a!==S)a=e;7(e===S){c.36();c.44()}}}7(E.14.1d)c.2L=c.36=c.44=c.2q=c.O=V;K a},4Z:J(c){L a=c;c=E.1s({},a);c.36=J(){7(a.36)a.36();a.7S=S};c.44=J(){7(a.44)a.44();a.7R=P};7(!c.2L)c.2L=c.7Q||T;7(c.2L.15==3)c.2L=a.2L.1a;7(!c.4S&&c.5w)c.4S=c.5w==c.2L?c.7P:c.5w;7(c.64==V&&c.63!=V){L b=T.1F,1h=T.1h;c.64=c.63+(b&&b.2v||1h&&1h.2v||0)-(b.62||0);c.7N=c.7L+(b&&b.2x||1h&&1h.2x||0)-(b.60||0)}7(!c.3c&&((c.4f||c.4f===0)?c.4f:c.5Z))c.3c=c.4f||c.5Z;7(!c.7b&&c.5Y)c.7b=c.5Y;7(!c.3c&&c.2G)c.3c=(c.2G&1?1:(c.2G&2?3:(c.2G&4?2:0)));K c},2y:{21:{4j:J(){5M();K},4h:J(){K}},3C:{4j:J(){7(E.14.1d)K S;E(6).2j("4P",E.16.2y.3C.2q);K P},4h:J(){7(E.14.1d)K S;E(6).3w("4P",E.16.2y.3C.2q);K P},2q:J(a){7(I(a,6))K P;18[0].U="3C";K E.16.1v.1i(6,18)}},3B:{4j:J(){7(E.14.1d)K S;E(6).2j("4O",E.16.2y.3B.2q);K P},4h:J(){7(E.14.1d)K S;E(6).3w("4O",E.16.2y.3B.2q);K P},2q:J(a){7(I(a,6))K P;18[0].U="3B";K E.16.1v.1i(6,18)}}}};E.1n.1s({2j:J(c,a,b){K c=="4H"?6.2X(c,a,b):6.R(J(){E.16.1b(6,c,b||a,b&&a)})},2X:J(d,b,c){K 6.R(J(){E.16.1b(6,d,J(a){E(6).3w(a);K(c||b).1i(6,18)},c&&b)})},3w:J(a,b){K 6.R(J(){E.16.1V(6,a,b)})},1N:J(c,a,b){K 6.R(J(){E.16.1N(c,a,6,P,b)})},5n:J(c,a,b){7(6[0])K E.16.1N(c,a,6[0],S,b);K 10},2g:J(){L b=18;K 6.4V(J(a){6.4N=0==6.4N?1:0;a.36();K b[6.4N].1i(6,18)||S})},7D:J(a,b){K 6.2j(\'3C\',a).2j(\'3B\',b)},21:J(a){5M();7(E.2Q)a.1P(T,E);N E.3A.1g(J(){K a.1P(6,E)});K 6}});E.1s({2Q:S,3A:[],21:J(){7(!E.2Q){E.2Q=P;7(E.3A){E.R(E.3A,J(){6.1i(T)});E.3A=V}E(T).5n("21")}}});L x=S;J 5M(){7(x)K;x=P;7(T.3F&&!E.14.2z)T.3F("5W",E.21,S);7(E.14.1d&&1e==3b)(J(){7(E.2Q)K;1S{T.1F.7B("26")}1X(3a){3z(18.3R,0);K}E.21()})();7(E.14.2z)T.3F("5W",J(){7(E.2Q)K;Q(L i=0;i<T.4L.M;i++)7(T.4L[i].2Y){3z(18.3R,0);K}E.21()},S);7(E.14.2d){L a;(J(){7(E.2Q)K;7(T.39!="5V"&&T.39!="1y"){3z(18.3R,0);K}7(a===10)a=E("W, 7a[7A=7z]").M;7(T.4L.M!=a){3z(18.3R,0);K}E.21()})()}E.16.1b(1e,"3U",E.21)}E.R(("7y,7x,3U,7w,5d,4H,4V,7v,"+"7G,7u,7t,4P,4O,7s,2k,"+"58,7K,7q,7p,3a").23(","),J(i,b){E.1n[b]=J(a){K a?6.2j(b,a):6.1N(b)}});L I=J(a,c){L b=a.4S;2b(b&&b!=c)1S{b=b.1a}1X(3a){b=c}K b==c};E(1e).2j("4H",J(){E("*").1b(T).3w()});E.1n.1s({3U:J(g,d,c){7(E.1q(g))K 6.2j("3U",g);L e=g.1f(" ");7(e>=0){L i=g.2K(e,g.M);g=g.2K(0,e)}c=c||J(){};L f="4Q";7(d)7(E.1q(d)){c=d;d=V}N{d=E.3m(d);f="61"}L h=6;E.3P({1c:g,U:f,1H:"3q",O:d,1y:J(a,b){7(b=="1W"||b=="5U")h.3q(i?E("<1x/>").3t(a.4b.1r(/<1m(.|\\s)*?\\/1m>/g,"")).2s(i):a.4b);h.R(c,[a.4b,b,a])}});K 6},7n:J(){K E.3m(6.5T())},5T:J(){K 6.2c(J(){K E.12(6,"3u")?E.2I(6.7m):6}).1E(J(){K 6.31&&!6.2Y&&(6.3k||/2k|6h/i.17(6.12)||/1u|1Z|3I/i.17(6.U))}).2c(J(i,c){L b=E(6).5O();K b==V?V:b.1k==1M?E.2c(b,J(a,i){K{31:c.31,1A:a}}):{31:c.31,1A:b}}).22()}});E.R("5S,6d,5R,6D,5Q,6m".23(","),J(i,o){E.1n[o]=J(f){K 6.2j(o,f)}});L B=(1B 3v).3L();E.1s({22:J(d,b,a,c){7(E.1q(b)){a=b;b=V}K E.3P({U:"4Q",1c:d,O:b,1W:a,1H:c})},7l:J(b,a){K E.22(b,V,a,"1m")},7k:J(c,b,a){K E.22(c,b,a,"3i")},7i:J(d,b,a,c){7(E.1q(b)){a=b;b={}}K E.3P({U:"61",1c:d,O:b,1W:a,1H:c})},85:J(a){E.1s(E.4I,a)},4I:{2a:P,U:"4Q",2U:0,5P:"4o/x-7h-3u-7g",5N:P,3l:P,O:V,6p:V,3I:V,49:{3M:"4o/3M, 1u/3M",3q:"1u/3q",1m:"1u/4m, 4o/4m",3i:"4o/3i, 1u/4m",1u:"1u/a7",4G:"*/*"}},4F:{},3P:J(s){L f,2W=/=\\?(&|$)/g,1z,O;s=E.1s(P,s,E.1s(P,{},E.4I,s));7(s.O&&s.5N&&1o s.O!="25")s.O=E.3m(s.O);7(s.1H=="4E"){7(s.U.2h()=="22"){7(!s.1c.1D(2W))s.1c+=(s.1c.1D(/\\?/)?"&":"?")+(s.4E||"7d")+"=?"}N 7(!s.O||!s.O.1D(2W))s.O=(s.O?s.O+"&":"")+(s.4E||"7d")+"=?";s.1H="3i"}7(s.1H=="3i"&&(s.O&&s.O.1D(2W)||s.1c.1D(2W))){f="4E"+B++;7(s.O)s.O=(s.O+"").1r(2W,"="+f+"$1");s.1c=s.1c.1r(2W,"="+f+"$1");s.1H="1m";1e[f]=J(a){O=a;1W();1y();1e[f]=10;1S{2V 1e[f]}1X(e){}7(h)h.34(g)}}7(s.1H=="1m"&&s.1T==V)s.1T=S;7(s.1T===S&&s.U.2h()=="22"){L i=(1B 3v()).3L();L j=s.1c.1r(/(\\?|&)4r=.*?(&|$)/,"$a4="+i+"$2");s.1c=j+((j==s.1c)?(s.1c.1D(/\\?/)?"&":"?")+"4r="+i:"")}7(s.O&&s.U.2h()=="22"){s.1c+=(s.1c.1D(/\\?/)?"&":"?")+s.O;s.O=V}7(s.2a&&!E.5H++)E.16.1N("5S");7((!s.1c.1f("a3")||!s.1c.1f("//"))&&s.1H=="1m"&&s.U.2h()=="22"){L h=T.3S("6f")[0];L g=T.3s("1m");g.3Q=s.1c;7(s.7c)g.a2=s.7c;7(!f){L l=S;g.9Z=g.9Y=J(){7(!l&&(!6.39||6.39=="5V"||6.39=="1y")){l=P;1W();1y();h.34(g)}}}h.38(g);K 10}L m=S;L k=1e.78?1B 78("9X.9V"):1B 76();k.9T(s.U,s.1c,s.3l,s.6p,s.3I);1S{7(s.O)k.4C("9R-9Q",s.5P);7(s.5C)k.4C("9O-5A-9N",E.4F[s.1c]||"9L, 9K 9I 9H 5z:5z:5z 9F");k.4C("X-9C-9A","76");k.4C("9z",s.1H&&s.49[s.1H]?s.49[s.1H]+", */*":s.49.4G)}1X(e){}7(s.6Y)s.6Y(k);7(s.2a)E.16.1N("6m",[k,s]);L c=J(a){7(!m&&k&&(k.39==4||a=="2U")){m=P;7(d){6I(d);d=V}1z=a=="2U"&&"2U"||!E.6X(k)&&"3a"||s.5C&&E.6J(k,s.1c)&&"5U"||"1W";7(1z=="1W"){1S{O=E.6W(k,s.1H)}1X(e){1z="5x"}}7(1z=="1W"){L b;1S{b=k.5q("6U-5A")}1X(e){}7(s.5C&&b)E.4F[s.1c]=b;7(!f)1W()}N E.5v(s,k,1z);1y();7(s.3l)k=V}};7(s.3l){L d=53(c,13);7(s.2U>0)3z(J(){7(k){k.9t();7(!m)c("2U")}},s.2U)}1S{k.9s(s.O)}1X(e){E.5v(s,k,V,e)}7(!s.3l)c();J 1W(){7(s.1W)s.1W(O,1z);7(s.2a)E.16.1N("5Q",[k,s])}J 1y(){7(s.1y)s.1y(k,1z);7(s.2a)E.16.1N("5R",[k,s]);7(s.2a&&!--E.5H)E.16.1N("6d")}K k},5v:J(s,a,b,e){7(s.3a)s.3a(a,b,e);7(s.2a)E.16.1N("6D",[a,s,e])},5H:0,6X:J(r){1S{K!r.1z&&9q.9p=="59:"||(r.1z>=6T&&r.1z<9n)||r.1z==6R||r.1z==9l||E.14.2d&&r.1z==10}1X(e){}K S},6J:J(a,c){1S{L b=a.5q("6U-5A");K a.1z==6R||b==E.4F[c]||E.14.2d&&a.1z==10}1X(e){}K S},6W:J(r,b){L c=r.5q("9k-U");L d=b=="3M"||!b&&c&&c.1f("3M")>=0;L a=d?r.9j:r.4b;7(d&&a.1F.28=="5x")6Q"5x";7(b=="1m")E.5g(a);7(b=="3i")a=6c("("+a+")");K a},3m:J(a){L s=[];7(a.1k==1M||a.5h)E.R(a,J(){s.1g(3r(6.31)+"="+3r(6.1A))});N Q(L j 1p a)7(a[j]&&a[j].1k==1M)E.R(a[j],J(){s.1g(3r(j)+"="+3r(6))});N s.1g(3r(j)+"="+3r(a[j]));K s.6a("&").1r(/%20/g,"+")}});E.1n.1s({1G:J(c,b){K c?6.2e({1R:"1G",27:"1G",1w:"1G"},c,b):6.1E(":1Z").R(J(){6.W.19=6.5s||"";7(E.1j(6,"19")=="2H"){L a=E("<"+6.28+" />").6y("1h");6.W.19=a.1j("19");7(6.W.19=="2H")6.W.19="3D";a.1V()}}).3h()},1I:J(b,a){K b?6.2e({1R:"1I",27:"1I",1w:"1I"},b,a):6.1E(":4d").R(J(){6.5s=6.5s||E.1j(6,"19");6.W.19="2H"}).3h()},6N:E.1n.2g,2g:J(a,b){K E.1q(a)&&E.1q(b)?6.6N(a,b):a?6.2e({1R:"2g",27:"2g",1w:"2g"},a,b):6.R(J(){E(6)[E(6).3H(":1Z")?"1G":"1I"]()})},9f:J(b,a){K 6.2e({1R:"1G"},b,a)},9d:J(b,a){K 6.2e({1R:"1I"},b,a)},9c:J(b,a){K 6.2e({1R:"2g"},b,a)},9a:J(b,a){K 6.2e({1w:"1G"},b,a)},99:J(b,a){K 6.2e({1w:"1I"},b,a)},97:J(c,a,b){K 6.2e({1w:a},c,b)},2e:J(l,k,j,h){L i=E.6P(k,j,h);K 6[i.2P===S?"R":"2P"](J(){7(6.15!=1)K S;L g=E.1s({},i);L f=E(6).3H(":1Z"),4A=6;Q(L p 1p l){7(l[p]=="1I"&&f||l[p]=="1G"&&!f)K E.1q(g.1y)&&g.1y.1i(6);7(p=="1R"||p=="27"){g.19=E.1j(6,"19");g.32=6.W.32}}7(g.32!=V)6.W.32="1Z";g.40=E.1s({},l);E.R(l,J(c,a){L e=1B E.2t(4A,g,c);7(/2g|1G|1I/.17(a))e[a=="2g"?f?"1G":"1I":a](l);N{L b=a.3X().1D(/^([+-]=)?([\\d+-.]+)(.*)$/),1Y=e.2m(P)||0;7(b){L d=2M(b[2]),2A=b[3]||"2S";7(2A!="2S"){4A.W[c]=(d||1)+2A;1Y=((d||1)/e.2m(P))*1Y;4A.W[c]=1Y+2A}7(b[1])d=((b[1]=="-="?-1:1)*d)+1Y;e.45(1Y,d,2A)}N e.45(1Y,a,"")}});K P})},2P:J(a,b){7(E.1q(a)||(a&&a.1k==1M)){b=a;a="2t"}7(!a||(1o a=="25"&&!b))K A(6[0],a);K 6.R(J(){7(b.1k==1M)A(6,a,b);N{A(6,a).1g(b);7(A(6,a).M==1)b.1i(6)}})},94:J(b,c){L a=E.3G;7(b)6.2P([]);6.R(J(){Q(L i=a.M-1;i>=0;i--)7(a[i].Y==6){7(c)a[i](P);a.72(i,1)}});7(!c)6.5p();K 6}});L A=J(b,c,a){7(!b)K 10;c=c||"2t";L q=E.O(b,c+"2P");7(!q||a)q=E.O(b,c+"2P",a?E.2I(a):[]);K q};E.1n.5p=J(a){a=a||"2t";K 6.R(J(){L q=A(6,a);q.4l();7(q.M)q[0].1i(6)})};E.1s({6P:J(b,a,c){L d=b&&b.1k==92?b:{1y:c||!c&&a||E.1q(b)&&b,2u:b,3Z:c&&a||a&&a.1k!=91&&a};d.2u=(d.2u&&d.2u.1k==51?d.2u:{90:8Z,9D:6T}[d.2u])||8X;d.5y=d.1y;d.1y=J(){7(d.2P!==S)E(6).5p();7(E.1q(d.5y))d.5y.1i(6)};K d},3Z:{70:J(p,n,b,a){K b+a*p},5j:J(p,n,b,a){K((-24.8V(p*24.8U)/2)+0.5)*a+b}},3G:[],3W:V,2t:J(b,c,a){6.11=c;6.Y=b;6.1l=a;7(!c.47)c.47={}}});E.2t.2l={4y:J(){7(6.11.30)6.11.30.1i(6.Y,[6.2J,6]);(E.2t.30[6.1l]||E.2t.30.4G)(6);7(6.1l=="1R"||6.1l=="27")6.Y.W.19="3D"},2m:J(a){7(6.Y[6.1l]!=V&&6.Y.W[6.1l]==V)K 6.Y[6.1l];L r=2M(E.1j(6.Y,6.1l,a));K r&&r>-8Q?r:2M(E.2o(6.Y,6.1l))||0},45:J(c,b,d){6.5B=(1B 3v()).3L();6.1Y=c;6.3h=b;6.2A=d||6.2A||"2S";6.2J=6.1Y;6.4B=6.4w=0;6.4y();L e=6;J t(a){K e.30(a)}t.Y=6.Y;E.3G.1g(t);7(E.3W==V){E.3W=53(J(){L a=E.3G;Q(L i=0;i<a.M;i++)7(!a[i]())a.72(i--,1);7(!a.M){6I(E.3W);E.3W=V}},13)}},1G:J(){6.11.47[6.1l]=E.1J(6.Y.W,6.1l);6.11.1G=P;6.45(0,6.2m());7(6.1l=="27"||6.1l=="1R")6.Y.W[6.1l]="8N";E(6.Y).1G()},1I:J(){6.11.47[6.1l]=E.1J(6.Y.W,6.1l);6.11.1I=P;6.45(6.2m(),0)},30:J(a){L t=(1B 3v()).3L();7(a||t>6.11.2u+6.5B){6.2J=6.3h;6.4B=6.4w=1;6.4y();6.11.40[6.1l]=P;L b=P;Q(L i 1p 6.11.40)7(6.11.40[i]!==P)b=S;7(b){7(6.11.19!=V){6.Y.W.32=6.11.32;6.Y.W.19=6.11.19;7(E.1j(6.Y,"19")=="2H")6.Y.W.19="3D"}7(6.11.1I)6.Y.W.19="2H";7(6.11.1I||6.11.1G)Q(L p 1p 6.11.40)E.1J(6.Y.W,p,6.11.47[p])}7(b&&E.1q(6.11.1y))6.11.1y.1i(6.Y);K S}N{L n=t-6.5B;6.4w=n/6.11.2u;6.4B=E.3Z[6.11.3Z||(E.3Z.5j?"5j":"70")](6.4w,n,0,1,6.11.2u);6.2J=6.1Y+((6.3h-6.1Y)*6.4B);6.4y()}K P}};E.2t.30={2v:J(a){a.Y.2v=a.2J},2x:J(a){a.Y.2x=a.2J},1w:J(a){E.1J(a.Y.W,"1w",a.2J)},4G:J(a){a.Y.W[a.1l]=a.2J+a.2A}};E.1n.5L=J(){L b=0,3b=0,Y=6[0],5l;7(Y)8M(E.14){L d=Y.1a,41=Y,1K=Y.1K,1L=Y.2i,5D=2d&&4s(5K)<8J&&!/a1/i.17(v),2T=E.1j(Y,"43")=="2T";7(Y.6G){L c=Y.6G();1b(c.26+24.2f(1L.1F.2v,1L.1h.2v),c.3b+24.2f(1L.1F.2x,1L.1h.2x));1b(-1L.1F.62,-1L.1F.60)}N{1b(Y.5G,Y.5F);2b(1K){1b(1K.5G,1K.5F);7(48&&!/^t(8H|d|h)$/i.17(1K.28)||2d&&!5D)2N(1K);7(!2T&&E.1j(1K,"43")=="2T")2T=P;41=/^1h$/i.17(1K.28)?41:1K;1K=1K.1K}2b(d&&d.28&&!/^1h|3q$/i.17(d.28)){7(!/^8G|1O.*$/i.17(E.1j(d,"19")))1b(-d.2v,-d.2x);7(48&&E.1j(d,"32")!="4d")2N(d);d=d.1a}7((5D&&(2T||E.1j(41,"43")=="4W"))||(48&&E.1j(41,"43")!="4W"))1b(-1L.1h.5G,-1L.1h.5F);7(2T)1b(24.2f(1L.1F.2v,1L.1h.2v),24.2f(1L.1F.2x,1L.1h.2x))}5l={3b:3b,26:b}}J 2N(a){1b(E.2o(a,"a8",P),E.2o(a,"a9",P))}J 1b(l,t){b+=4s(l)||0;3b+=4s(t)||0}K 5l}})();',62,631,'||||||this|if||||||||||||||||||||||||||||||||||||||function|return|var|length|else|data|true|for|each|false|document|type|null|style||elem||undefined|options|nodeName||browser|nodeType|event|test|arguments|display|parentNode|add|url|msie|window|indexOf|push|body|apply|css|constructor|prop|script|fn|typeof|in|isFunction|replace|extend|className|text|handle|opacity|div|complete|status|value|new|firstChild|match|filter|documentElement|show|dataType|hide|attr|offsetParent|doc|Array|trigger|table|call|break|height|try|cache|tbody|remove|success|catch|start|hidden||ready|get|split|Math|string|left|width|tagName|ret|global|while|map|safari|animate|max|toggle|toLowerCase|ownerDocument|bind|select|prototype|cur||curCSS|selected|handler|done|find|fx|duration|scrollLeft|id|scrollTop|special|opera|unit|nextSibling|stack|guid|toUpperCase|pushStack|button|none|makeArray|now|slice|target|parseFloat|border|exec|queue|isReady|events|px|fixed|timeout|delete|jsre|one|disabled|nth|step|name|overflow|inArray|removeChild|removeData|preventDefault|merge|appendChild|readyState|error|top|which|innerHTML|multiFilter|rl|trim|end|json|first|checked|async|param|elems|insertBefore|childNodes|html|encodeURIComponent|createElement|append|form|Date|unbind|color|grep|setTimeout|readyList|mouseleave|mouseenter|block|isXMLDoc|addEventListener|timers|is|password|last|runtimeStyle|getTime|xml|jQuery|domManip|ajax|src|callee|getElementsByTagName|selectedIndex|load|object|timerId|toString|has|easing|curAnim|offsetChild|args|position|stopPropagation|custom|props|orig|mozilla|accepts|clean|responseText|defaultView|visible|String|charCode|float|teardown|on|setup|nodeIndex|shift|javascript|currentStyle|application|child|RegExp|_|parseInt|previousSibling|dir|tr|state|empty|update|getAttribute|self|pos|setRequestHeader|input|jsonp|lastModified|_default|unload|ajaxSettings|unshift|getComputedStyle|styleSheets|getPropertyValue|lastToggle|mouseout|mouseover|GET|andSelf|relatedTarget|init|visibility|click|absolute|index|container|fix|outline|Number|removeAttribute|setInterval|prevObject|classFilter|not|unique|submit|file|after|windowData|deep|scroll|client|triggered|globalEval|jquery|sibling|swing|clone|results|wrapAll|triggerHandler|lastChild|dequeue|getResponseHeader|createTextNode|oldblock|checkbox|radio|handleError|fromElement|parsererror|old|00|Modified|startTime|ifModified|safari2|getWH|offsetTop|offsetLeft|active|values|getElementById|version|offset|bindReady|processData|val|contentType|ajaxSuccess|ajaxComplete|ajaxStart|serializeArray|notmodified|loaded|DOMContentLoaded|Width|ctrlKey|keyCode|clientTop|POST|clientLeft|clientX|pageX|exclusive|detachEvent|removeEventListener|swap|cloneNode|join|attachEvent|eval|ajaxStop|substr|head|parse|textarea|reset|image|zoom|odd|ajaxSend|even|before|username|prepend|expr|quickClass|uuid|quickID|quickChild|continue|textContent|appendTo|contents|evalScript|parent|defaultValue|ajaxError|setArray|compatMode|getBoundingClientRect|styleFloat|clearInterval|httpNotModified|nodeValue|100|alpha|_toggle|href|speed|throw|304|replaceWith|200|Last|colgroup|httpData|httpSuccess|beforeSend|eq|linear|concat|splice|fieldset|multiple|cssFloat|XMLHttpRequest|webkit|ActiveXObject|CSS1Compat|link|metaKey|scriptCharset|callback|col|pixelLeft|urlencoded|www|post|hasClass|getJSON|getScript|elements|serialize|black|keyup|keypress|solid|change|mousemove|mouseup|dblclick|resize|focus|blur|stylesheet|rel|doScroll|round|hover|padding|offsetHeight|mousedown|offsetWidth|Bottom|Top|keydown|clientY|Right|pageY|Left|toElement|srcElement|cancelBubble|returnValue|charAt|0n|substring|animated|header|noConflict|line|enabled|innerText|contains|only|weight|ajaxSetup|font|size|gt|lt|uFFFF|u0128|417|Boolean|inner|Height|toggleClass|removeClass|addClass|removeAttr|replaceAll|insertAfter|prependTo|contentWindow|contentDocument|wrap|iframe|children|siblings|prevAll|nextAll|prev|wrapInner|next|parents|maxLength|maxlength|readOnly|readonly|reverse|class|htmlFor|inline|able|boxModel|522|setData|compatible|with|1px|ie|getData|10000|ra|it|rv|PI|cos|userAgent|400|navigator|600|slow|Function|Object|array|stop|ig|NaN|fadeTo|option|fadeOut|fadeIn|setAttribute|slideToggle|slideUp|changed|slideDown|be|can|property|responseXML|content|1223|getAttributeNode|300|method|protocol|location|action|send|abort|cssText|th|td|cap|specified|Accept|With|colg|Requested|fast|tfoot|GMT|thead|1970|Jan|attributes|01|Thu|leg|Since|If|opt|Type|Content|embed|open|area|XMLHTTP|hr|Microsoft|onreadystatechange|onload|meta|adobeair|charset|http|1_|img|br|plain|borderLeftWidth|borderTopWidth|abbr'.split('|'),0,{})) Modified: slashjp/branches/upstream/current/plugins/Ajax/htdocs/images/nodnix.js =================================================================== --- slashjp/branches/upstream/current/plugins/Ajax/htdocs/images/nodnix.js 2008-03-31 12:09:17 UTC (rev 559) +++ slashjp/branches/upstream/current/plugins/Ajax/htdocs/images/nodnix.js 2008-04-01 03:35:14 UTC (rev 560) @@ -1,5 +1,5 @@ // _*_ Mode: JavaScript; tab-width: 8; indent-tabs-mode: true _*_ -// $Id: nodnix.js,v 1.9 2008/02/20 18:43:31 scc Exp $ +// $Id: nodnix.js,v 1.17 2008/03/14 15:48:06 scc Exp $ var nod_completer = null; var nix_completer = null; @@ -100,6 +100,17 @@ firehose_up_down(g_nodnix_item_id, up_down); } +function nodnix_not_tag( old_tag ) { + var new_tag = old_tag[0]=='!' ? old_tag.slice(1) : '!'+old_tag; + createTag(new_tag, g_nodnix_item_id, "firehose"); + var tag_list = _get_nodnix('ol'); + // XXX not a good idea if the tag happens to be 'span' or 'li', etc + tag_list.innerHTML = tag_list.innerHTML.replace(old_tag, new_tag, "g"); +} + +function nodnix_del_tag( tag ) { +} + function hide_nod_menu() { get_nod_menu().style.display = 'none'; } @@ -117,7 +128,7 @@ } else { if ( g_pending_hidemenu ) clearTimeout(g_pending_hidemenu); - g_pending_hidemenu = setTimeout("hide_nodnix_menu()", delay); + g_pending_hidemenu = setTimeout(hide_nodnix_menu, delay); } } @@ -204,7 +215,21 @@ YAHOO.util.Dom.removeClass(get_nix_menu(), 'soon'); } +function refresh_tag_bar( tag_list ) { + // ajax request to fill the user tags list + var params = {}; + params['op'] = 'tags_get_user_firehose'; + params['id'] = g_nodnix_item_id; + params['nodnix'] = 1; + ajax_update(params, tag_list, {}); +} + function begin_nodnix_editing() { + if ( is_firehose_playing() ) { + firehose_pause(); + end_nodnix_editing.restore_firehose_state = firehose_play; + } + get_nodnix_listener().disable(); YAHOO.util.Dom.addClass(get_nod_menu(), 'soon'); YAHOO.util.Dom.addClass(get_nix_menu(), 'soon'); @@ -215,17 +240,22 @@ var input = _get_nodnix('input'); input.value = ""; input.focus(); - - _get_nodnix('ol').innerHTML = ""; + var tag_list = _get_nodnix('ol'); + tag_list.innerHTML = ""; + refresh_tag_bar(tag_list); + (input.getAttribute("updown")=="+" ? nod_completer : nix_completer).sendQuery(); - setTimeout("soon_is_now()", 225); + setTimeout(soon_is_now, 225); } function end_nodnix_editing() { YAHOO.util.Dom.removeClass(get_nod_menu(), 'editing'); YAHOO.util.Dom.removeClass(get_nix_menu(), 'editing'); + end_nodnix_editing.restore_firehose_state(); + end_nodnix_editing.restore_firehose_state = function(){} } +end_nodnix_editing.restore_firehose_state = function(){} function handle_nodnix_blur( type, args ) { hide_nodnix_menu(); @@ -239,13 +269,16 @@ nodnix_tag(tagname); // now 'harden' the tag var list = _get_nodnix('ol'); - list.innerHTML = '<li>' + tagname + '</li>' + list.innerHTML; + list.innerHTML = handle_nodnix_select.template_string.split('$').join(tagname) + list.innerHTML; _get_nodnix('input').value = ""; } if ( !stay_open ) hide_nodnix_menu(); } + // WARNING: keep this string in sync with tagsnodnixuser;misc;default +handle_nodnix_select.template_string = '<li>$<span class="tag-actions"><a class="not-tag" onmousedown="nodnix_not_tag(\'$\'); return false" href="#">!</a> <a class="del-tag" onmousedown="nodnix_del_tag(\'$\'); return false" href="#">x</a></span></li>'; + function handle_completer_key( type, args ) { var key = args[0]; var event = args[1]; Deleted: slashjp/branches/upstream/current/plugins/Ajax/htdocs/images/prototype.js =================================================================== --- slashjp/branches/upstream/current/plugins/Ajax/htdocs/images/prototype.js 2008-03-31 12:09:17 UTC (rev 559) +++ slashjp/branches/upstream/current/plugins/Ajax/htdocs/images/prototype.js 2008-04-01 03:35:14 UTC (rev 560) @@ -1,1785 +0,0 @@ -/* Prototype JavaScript framework, version 1.4.0 - * (c) 2005 Sam Stephenson <sam****@conio*****> - * - * THIS FILE IS AUTOMATICALLY GENERATED. When sending patches, please diff - * against the source tree, available from the Prototype darcs repository. - * - * Prototype is freely distributable under the terms of an MIT-style license. - * - * For details, see the Prototype web site: http://prototype.conio.net/ - * -/*--------------------------------------------------------------------------*/ - -var Prototype = { - Version: '1.4.0', - ScriptFragment: '(?:<script.*?>)((\n|\r|.)*?)(?:<\/script>)', - - emptyFunction: function() {}, - K: function(x) {return x} -} - -var Class = { - create: function() { - return function() { - this.initialize.apply(this, arguments); - } - } -} - -var Abstract = new Object(); - -Object.extend = function(destination, source) { - for (property in source) { - destination[property] = source[property]; - } - return destination; -} - -Object.inspect = function(object) { - try { - if (object == undefined) return 'undefined'; - if (object == null) return 'null'; - return object.inspect ? object.inspect() : object.toString(); - } catch (e) { - if (e instanceof RangeError) return '...'; - throw e; - } -} - -Function.prototype.bind = function() { - var __method = this, args = $A(arguments), object = args.shift(); - return function() { - return __method.apply(object, args.concat($A(arguments))); - } -} - -Function.prototype.bindAsEventListener = function(object) { - var __method = this; - return function(event) { - return __method.call(object, event || window.event); - } -} - -Object.extend(Number.prototype, { - toColorPart: function() { - var digits = this.toString(16); - if (this < 16) return '0' + digits; - return digits; - }, - - succ: function() { - return this + 1; - }, - - times: function(iterator) { - $R(0, this, true).each(iterator); - return this; - } -}); - -var Try = { - these: function() { - var returnValue; - - for (var i = 0; i < arguments.length; i++) { - var lambda = arguments[i]; - try { - returnValue = lambda(); - break; - } catch (e) {} - } - - return returnValue; - } -} - -/*--------------------------------------------------------------------------*/ - -var PeriodicalExecuter = Class.create(); -PeriodicalExecuter.prototype = { - initialize: function(callback, frequency) { - this.callback = callback; - this.frequency = frequency; - this.currentlyExecuting = false; - - this.registerCallback(); - }, - - registerCallback: function() { - setInterval(this.onTimerEvent.bind(this), this.frequency * 1000); - }, - - onTimerEvent: function() { - if (!this.currentlyExecuting) { - try { - this.currentlyExecuting = true; - this.callback(); - } finally { - this.currentlyExecuting = false; - } - } - } -} - -/*--------------------------------------------------------------------------*/ - -function $() { - var elements = new Array(); - - for (var i = 0; i < arguments.length; i++) { - var element = arguments[i]; - if (typeof element == 'string') - element = document.getElementById(element); - - if (arguments.length == 1) - return element; - - elements.push(element); - } - - return elements; -} -Object.extend(String.prototype, { - stripTags: function() { - return this.replace(/<\/?[^>]+>/gi, ''); - }, - - stripScripts: function() { - return this.replace(new RegExp(Prototype.ScriptFragment, 'img'), ''); - }, - - extractScripts: function() { - var matchAll = new RegExp(Prototype.ScriptFragment, 'img'); - var matchOne = new RegExp(Prototype.ScriptFragment, 'im'); - return (this.match(matchAll) || []).map(function(scriptTag) { - return (scriptTag.match(matchOne) || ['', ''])[1]; - }); - }, - - evalScripts: function() { - return this.extractScripts().map(eval); - }, - - escapeHTML: function() { - var div = document.createElement('div'); - var text = document.createTextNode(this); - div.appendChild(text); - return div.innerHTML; - }, - - unescapeHTML: function() { - var div = document.createElement('div'); - div.innerHTML = this.stripTags(); - return div.childNodes[0] ? div.childNodes[0].nodeValue : ''; - }, - - toQueryParams: function() { - var pairs = this.match(/^\??(.*)$/)[1].split('&'); - return pairs.inject({}, function(params, pairString) { - var pair = pairString.split('='); - params[pair[0]] = pair[1]; - return params; - }); - }, - - toArray: function() { - return this.split(''); - }, - - camelize: function() { - var oStringList = this.split('-'); - if (oStringList.length == 1) return oStringList[0]; - - var camelizedString = this.indexOf('-') == 0 - ? oStringList[0].charAt(0).toUpperCase() + oStringList[0].substring(1) - : oStringList[0]; - - for (var i = 1, len = oStringList.length; i < len; i++) { - var s = oStringList[i]; - camelizedString += s.charAt(0).toUpperCase() + s.substring(1); - } - - return camelizedString; - }, - - inspect: function() { - return "'" + this.replace('\\', '\\\\').replace("'", '\\\'') + "'"; - } -}); - -String.prototype.parseQuery = String.prototype.toQueryParams; - -var $break = new Object(); -var $continue = new Object(); - -var Enumerable = { - each: function(iterator) { - var index = 0; - try { - this._each(function(value) { - try { - iterator(value, index++); - } catch (e) { - if (e != $continue) throw e; - } - }); - } catch (e) { - if (e != $break) throw e; - } - }, - - all: function(iterator) { - var result = true; - this.each(function(value, index) { - result = result && !!(iterator || Prototype.K)(value, index); - if (!result) throw $break; - }); - return result; - }, - - any: function(iterator) { - var result = true; - this.each(function(value, index) { - if (result = !!(iterator || Prototype.K)(value, index)) - throw $break; - }); - return result; - }, - - collect: function(iterator) { - var results = []; - this.each(function(value, index) { - results.push(iterator(value, index)); - }); - return results; - }, - - detect: function (iterator) { - var result; - this.each(function(value, index) { - if (iterator(value, index)) { - result = value; - throw $break; - } - }); - return result; - }, - - findAll: function(iterator) { - var results = []; - this.each(function(value, index) { - if (iterator(value, index)) - results.push(value); - }); - return results; - }, - - grep: function(pattern, iterator) { - var results = []; - this.each(function(value, index) { - var stringValue = value.toString(); - if (stringValue.match(pattern)) - results.push((iterator || Prototype.K)(value, index)); - }) - return results; - }, - - include: function(object) { - var found = false; - this.each(function(value) { - if (value == object) { - found = true; - throw $break; - } - }); - return found; - }, - - inject: function(memo, iterator) { - this.each(function(value, index) { - memo = iterator(memo, value, index); - }); - return memo; - }, - - invoke: function(method) { - var args = $A(arguments).slice(1); - return this.collect(function(value) { - return value[method].apply(value, args); - }); - }, - - max: function(iterator) { - var result; - this.each(function(value, index) { - value = (iterator || Prototype.K)(value, index); - if (value >= (result || value)) - result = value; - }); - return result; - }, - - min: function(iterator) { - var result; - this.each(function(value, index) { - value = (iterator || Prototype.K)(value, index); - if (value <= (result || value)) - result = value; - }); - return result; - }, - - partition: function(iterator) { - var trues = [], falses = []; - this.each(function(value, index) { - ((iterator || Prototype.K)(value, index) ? - trues : falses).push(value); - }); - return [trues, falses]; - }, - - pluck: function(property) { - var results = []; - this.each(function(value, index) { - results.push(value[property]); - }); - return results; - }, - - reject: function(iterator) { - var results = []; - this.each(function(value, index) { - if (!iterator(value, index)) - results.push(value); - }); - return results; - }, - - sortBy: function(iterator) { - return this.collect(function(value, index) { - return {value: value, criteria: iterator(value, index)}; - }).sort(function(left, right) { - var a = left.criteria, b = right.criteria; - return a < b ? -1 : a > b ? 1 : 0; - }).pluck('value'); - }, - - toArray: function() { - return this.collect(Prototype.K); - }, - - zip: function() { - var iterator = Prototype.K, args = $A(arguments); - if (typeof args.last() == 'function') - iterator = args.pop(); - - var collections = [this].concat(args).map($A); - return this.map(function(value, index) { - iterator(value = collections.pluck(index)); - return value; - }); - }, - - inspect: function() { - return '#<Enumerable:' + this.toArray().inspect() + '>'; - } -} - -Object.extend(Enumerable, { - map: Enumerable.collect, - find: Enumerable.detect, - select: Enumerable.findAll, - member: Enumerable.include, - entries: Enumerable.toArray -}); -var $A = Array.from = function(iterable) { - if (!iterable) return []; - if (iterable.toArray) { - return iterable.toArray(); - } else { - var results = []; - for (var i = 0; i < iterable.length; i++) - results.push(iterable[i]); - return results; - } -} - -Object.extend(Array.prototype, Enumerable); - -Array.prototype._reverse = Array.prototype.reverse; - -Object.extend(Array.prototype, { - _each: function(iterator) { - for (var i = 0; i < this.length; i++) - iterator(this[i]); - }, - - clear: function() { - this.length = 0; - return this; - }, - - first: function() { - return this[0]; - }, - - last: function() { - return this[this.length - 1]; - }, - - compact: function() { - return this.select(function(value) { - return value != undefined || value != null; - }); - }, - - flatten: function() { - return this.inject([], function(array, value) { - return array.concat(value.constructor == Array ? - value.flatten() : [value]); - }); - }, - - without: function() { - var values = $A(arguments); - return this.select(function(value) { - return !values.include(value); - }); - }, - - indexOf: function(object) { - for (var i = 0; i < this.length; i++) - if (this[i] == object) return i; - return -1; - }, - - reverse: function(inline) { - return (inline !== false ? this : this.toArray())._reverse(); - }, - - shift: function() { - var result = this[0]; - for (var i = 0; i < this.length - 1; i++) - this[i] = this[i + 1]; - this.length--; - return result; - }, - - inspect: function() { - return '[' + this.map(Object.inspect).join(', ') + ']'; - } -}); -var Hash = { - _each: function(iterator) { - for (key in this) { - var value = this[key]; - if (typeof value == 'function') continue; - - var pair = [key, value]; - pair.key = key; - pair.value = value; - iterator(pair); - } - }, - - keys: function() { - return this.pluck('key'); - }, - - values: function() { - return this.pluck('value'); - }, - - merge: function(hash) { - return $H(hash).inject($H(this), function(mergedHash, pair) { - mergedHash[pair.key] = pair.value; - return mergedHash; - }); - }, - - toQueryString: function() { - return this.map(function(pair) { - return pair.map(encodeURIComponent).join('='); - }).join('&'); - }, - - inspect: function() { - return '#<Hash:{' + this.map(function(pair) { - return pair.map(Object.inspect).join(': '); - }).join(', ') + '}>'; - } -} - -function $H(object) { - var hash = Object.extend({}, object || {}); - Object.extend(hash, Enumerable); - Object.extend(hash, Hash); - return hash; -} -ObjectRange = Class.create(); -Object.extend(ObjectRange.prototype, Enumerable); -Object.extend(ObjectRange.prototype, { - initialize: function(start, end, exclusive) { - this.start = start; - this.end = end; - this.exclusive = exclusive; - }, - - _each: function(iterator) { - var value = this.start; - do { - iterator(value); - value = value.succ(); - } while (this.include(value)); - }, - - include: function(value) { - if (value < this.start) - return false; - if (this.exclusive) - return value < this.end; - return value <= this.end; - } -}); - -var $R = function(start, end, exclusive) { - return new ObjectRange(start, end, exclusive); -} - -var Ajax = { - getTransport: function() { - return Try.these( - function() {return new ActiveXObject('Msxml2.XMLHTTP')}, - function() {return new ActiveXObject('Microsoft.XMLHTTP')}, - function() {return new XMLHttpRequest()} - ) || false; - }, - - activeRequestCount: 0 -} - -Ajax.Responders = { - responders: [], - - _each: function(iterator) { - this.responders._each(iterator); - }, - - register: function(responderToAdd) { - if (!this.include(responderToAdd)) - this.responders.push(responderToAdd); - }, - - unregister: function(responderToRemove) { - this.responders = this.responders.without(responderToRemove); - }, - - dispatch: function(callback, request, transport, json) { - this.each(function(responder) { - if (responder[callback] && typeof responder[callback] == 'function') { - try { - responder[callback].apply(responder, [request, transport, json]); - } catch (e) {} - } - }); - } -}; - -Object.extend(Ajax.Responders, Enumerable); - -Ajax.Responders.register({ - onCreate: function() { - Ajax.activeRequestCount++; - }, - - onComplete: function() { - Ajax.activeRequestCount--; - } -}); - -Ajax.Base = function() {}; -Ajax.Base.prototype = { - setOptions: function(options) { - this.options = { - method: 'post', - asynchronous: true, - parameters: '' - } - Object.extend(this.options, options || {}); - }, - - responseIsSuccess: function() { - return this.transport.status == undefined - || this.transport.status == 0 - || (this.transport.status >= 200 && this.transport.status < 300); - }, - - responseIsFailure: function() { - return !this.responseIsSuccess(); - } -} - -Ajax.Request = Class.create(); -Ajax.Request.Events = - ['Uninitialized', 'Loading', 'Loaded', 'Interactive', 'Complete']; - -Ajax.Request.prototype = Object.extend(new Ajax.Base(), { - initialize: function(url, options) { - this.transport = Ajax.getTransport(); - this.setOptions(options); - this.request(url); - }, - - request: function(url) { - var parameters = this.options.parameters || ''; - if (parameters.length > 0) parameters += '&_='; - - try { - this.url = url; - if (this.options.method == 'get' && parameters.length > 0) - this.url += (this.url.match(/\?/) ? '&' : '?') + parameters; - - Ajax.Responders.dispatch('onCreate', this, this.transport); - - this.transport.open(this.options.method, this.url, - this.options.asynchronous); - - if (this.options.asynchronous) { - this.transport.onreadystatechange = this.onStateChange.bind(this); - setTimeout((function() {this.respondToReadyState(1)}).bind(this), 10); - } - - this.setRequestHeaders(); - - var body = this.options.postBody ? this.options.postBody : parameters; - this.transport.send(this.options.method == 'post' ? body : null); - - } catch (e) { - this.dispatchException(e); - } - }, - - setRequestHeaders: function() { - var requestHeaders = - ['X-Requested-With', 'XMLHttpRequest', - 'X-Prototype-Version', Prototype.Version]; - - if (this.options.method == 'post') { - requestHeaders.push('Content-type', - 'application/x-www-form-urlencoded'); - - /* Force "Connection: close" for Mozilla browsers to work around - * a bug where XMLHttpReqeuest sends an incorrect Content-length - * header. See Mozilla Bugzilla #246651. - */ - if (this.transport.overrideMimeType) - requestHeaders.push('Connection', 'close'); - } - - if (this.options.requestHeaders) - requestHeaders.push.apply(requestHeaders, this.options.requestHeaders); - - for (var i = 0; i < requestHeaders.length; i += 2) - this.transport.setRequestHeader(requestHeaders[i], requestHeaders[i+1]); - }, - - onStateChange: function() { - var readyState = this.transport.readyState; - if (readyState != 1) - this.respondToReadyState(this.transport.readyState); - }, - - header: function(name) { - try { - return this.transport.getResponseHeader(name); - } catch (e) {} - }, - - evalJSON: function() { - try { - return eval(this.header('X-JSON')); - } catch (e) {} - }, - - evalResponse: function() { - try { - return eval(this.transport.responseText); - } catch (e) { - this.dispatchException(e); - } - }, - - respondToReadyState: function(readyState) { - var event = Ajax.Request.Events[readyState]; - var transport = this.transport, json = this.evalJSON(); - - if (event == 'Complete') { - try { - (this.options['on' + this.transport.status] - || this.options['on' + (this.responseIsSuccess() ? 'Success' : 'Failure')] - || Prototype.emptyFunction)(transport, json); - } catch (e) { - this.dispatchException(e); - } - - if ((this.header('Content-type') || '').match(/^text\/javascript/i)) - this.evalResponse(); - } - - try { - (this.options['on' + event] || Prototype.emptyFunction)(transport, json); - Ajax.Responders.dispatch('on' + event, this, transport, json); - } catch (e) { - this.dispatchException(e); - } - - /* Avoid memory leak in MSIE: clean up the oncomplete event handler */ - if (event == 'Complete') - this.transport.onreadystatechange = Prototype.emptyFunction; - }, - - dispatchException: function(exception) { - (this.options.onException || Prototype.emptyFunction)(this, exception); - Ajax.Responders.dispatch('onException', this, exception); - } -}); - -Ajax.Updater = Class.create(); - -Object.extend(Object.extend(Ajax.Updater.prototype, Ajax.Request.prototype), { - initialize: function(container, url, options) { - this.containers = { - success: container.success ? $(container.success) : $(container), - failure: container.failure ? $(container.failure) : - (container.success ? null : $(container)) - } - - this.transport = Ajax.getTransport(); - this.setOptions(options); - - var onComplete = this.options.onComplete || Prototype.emptyFunction; - this.options.onComplete = (function(transport, object) { - this.updateContent(); - onComplete(transport, object); - }).bind(this); - - this.request(url); - }, - - updateContent: function() { - var receiver = this.responseIsSuccess() ? - this.containers.success : this.containers.failure; - var response = this.transport.responseText; - - if (!this.options.evalScripts) - response = response.stripScripts(); - - if (receiver) { - if (this.options.insertion) { - new this.options.insertion(receiver, response); - } else { - Element.update(receiver, response); - } - } - - if (this.responseIsSuccess()) { - if (this.onComplete) - setTimeout(this.onComplete.bind(this), 10); - } - } -}); - -Ajax.PeriodicalUpdater = Class.create(); -Ajax.PeriodicalUpdater.prototype = Object.extend(new Ajax.Base(), { - initialize: function(container, url, options) { - this.setOptions(options); - this.onComplete = this.options.onComplete; - - this.frequency = (this.options.frequency || 2); - this.decay = (this.options.decay || 1); - - this.updater = {}; - this.container = container; - this.url = url; - - this.start(); - }, - - start: function() { - this.options.onComplete = this.updateComplete.bind(this); - this.onTimerEvent(); - }, - - stop: function() { - this.updater.onComplete = undefined; - clearTimeout(this.timer); - (this.onComplete || Prototype.emptyFunction).apply(this, arguments); - }, - - updateComplete: function(request) { - if (this.options.decay) { - this.decay = (request.responseText == this.lastText ? - this.decay * this.options.decay : 1); - - this.lastText = request.responseText; - } - this.timer = setTimeout(this.onTimerEvent.bind(this), - this.decay * this.frequency * 1000); - }, - - onTimerEvent: function() { - this.updater = new Ajax.Updater(this.container, this.url, this.options); - } -}); -document.getElementsByClassName = function(className, parentElement) { - var children = ($(parentElement) || document.body).getElementsByTagName('*'); - return $A(children).inject([], function(elements, child) { - if (child.className.match(new RegExp("(^|\\s)" + className + "(\\s|$)"))) - elements.push(child); - return elements; - }); -} - -/*--------------------------------------------------------------------------*/ - -if (!window.Element) { - var Element = new Object(); -} - -Object.extend(Element, { - visible: function(element) { - return $(element).style.display != 'none'; - }, - - toggle: function() { - for (var i = 0; i < arguments.length; i++) { - var element = $(arguments[i]); - Element[Element.visible(element) ? 'hide' : 'show'](element); - } - }, - - hide: function() { - for (var i = 0; i < arguments.length; i++) { - var element = $(arguments[i]); - element.style.display = 'none'; - } - }, - - show: function() { - for (var i = 0; i < arguments.length; i++) { - var element = $(arguments[i]); - element.style.display = ''; - } - }, - - remove: function(element) { - element = $(element); - element.parentNode.removeChild(element); - }, - - update: function(element, html) { - $(element).innerHTML = html.stripScripts(); - setTimeout(function() {html.evalScripts()}, 10); - }, - - getHeight: function(element) { - element = $(element); - return element.offsetHeight; - }, - - classNames: function(element) { - return new Element.ClassNames(element); - }, - - hasClassName: function(element, className) { - if (!(element = $(element))) return; - return Element.classNames(element).include(className); - }, - - addClassName: function(element, className) { - if (!(element = $(element))) return; - return Element.classNames(element).add(className); - }, - - removeClassName: function(element, className) { - if (!(element = $(element))) return; - return Element.classNames(element).remove(className); - }, - - // removes whitespace-only text node children - cleanWhitespace: function(element) { - element = $(element); - for (var i = 0; i < element.childNodes.length; i++) { - var node = element.childNodes[i]; - if (node.nodeType == 3 && !/\S/.test(node.nodeValue)) - Element.remove(node); - } - }, - - empty: function(element) { - return $(element).innerHTML.match(/^\s*$/); - }, - - scrollTo: function(element) { - element = $(element); - var x = element.x ? element.x : element.offsetLeft, - y = element.y ? element.y : element.offsetTop; - window.scrollTo(x, y); - }, - - getStyle: function(element, style) { - element = $(element); - var value = element.style[style.camelize()]; - if (!value) { - if (document.defaultView && document.defaultView.getComputedStyle) { - var css = document.defaultView.getComputedStyle(element, null); - value = css ? css.getPropertyValue(style) : null; - } else if (element.currentStyle) { - value = element.currentStyle[style.camelize()]; - } - } - - if (window.opera && ['left', 'top', 'right', 'bottom'].include(style)) - if (Element.getStyle(element, 'position') == 'static') value = 'auto'; - - return value == 'auto' ? null : value; - }, - - setStyle: function(element, style) { - element = $(element); - for (name in style) - element.style[name.camelize()] = style[name]; - }, - - getDimensions: function(element) { - element = $(element); - if (Element.getStyle(element, 'display') != 'none') - return {width: element.offsetWidth, height: element.offsetHeight}; - - // All *Width and *Height properties give 0 on elements with display none, - // so enable the element temporarily - var els = element.style; - var originalVisibility = els.visibility; - var originalPosition = els.position; - els.visibility = 'hidden'; - els.position = 'absolute'; - els.display = ''; - var originalWidth = element.clientWidth; - var originalHeight = element.clientHeight; - els.display = 'none'; - els.position = originalPosition; - els.visibility = originalVisibility; - return {width: originalWidth, height: originalHeight}; - }, - - makePositioned: function(element) { - element = $(element); - var pos = Element.getStyle(element, 'position'); - if (pos == 'static' || !pos) { - element._madePositioned = true; - element.style.position = 'relative'; - // Opera returns the offset relative to the positioning context, when an - // element is position relative but top and left have not been defined - if (window.opera) { - element.style.top = 0; - element.style.left = 0; - } - } - }, - - undoPositioned: function(element) { - element = $(element); - if (element._madePositioned) { - element._madePositioned = undefined; - element.style.position = - element.style.top = - element.style.left = - element.style.bottom = - element.style.right = ''; - } - }, - - makeClipping: function(element) { - element = $(element); - if (element._overflow) return; - element._overflow = element.style.overflow; - if ((Element.getStyle(element, 'overflow') || 'visible') != 'hidden') - element.style.overflow = 'hidden'; - }, - - undoClipping: function(element) { - element = $(element); - if (element._overflow) return; - element.style.overflow = element._overflow; - element._overflow = undefined; - } -}); - -var Toggle = new Object(); -Toggle.display = Element.toggle; - -/*--------------------------------------------------------------------------*/ - -Abstract.Insertion = function(adjacency) { - this.adjacency = adjacency; -} - -Abstract.Insertion.prototype = { - initialize: function(element, content) { - this.element = $(element); - this.content = content.stripScripts(); - - if (this.adjacency && this.element.insertAdjacentHTML) { - try { - this.element.insertAdjacentHTML(this.adjacency, this.content); - } catch (e) { - if (this.element.tagName.toLowerCase() == 'tbody') { - this.insertContent(this.contentFromAnonymousTable()); - } else { - throw e; - } - } - } else { - this.range = this.element.ownerDocument.createRange(); - if (this.initializeRange) this.initializeRange(); - this.insertContent([this.range.createContextualFragment(this.content)]); - } - - setTimeout(function() {content.evalScripts()}, 10); - }, - - contentFromAnonymousTable: function() { - var div = document.createElement('div'); - div.innerHTML = '<table><tbody>' + this.content + '</tbody></table>'; - return $A(div.childNodes[0].childNodes[0].childNodes); - } -} - -var Insertion = new Object(); - -Insertion.Before = Class.create(); -Insertion.Before.prototype = Object.extend(new Abstract.Insertion('beforeBegin'), { - initializeRange: function() { - this.range.setStartBefore(this.element); - }, - - insertContent: function(fragments) { - fragments.each((function(fragment) { - this.element.parentNode.insertBefore(fragment, this.element); - }).bind(this)); - } -}); - -Insertion.Top = Class.create(); -Insertion.Top.prototype = Object.extend(new Abstract.Insertion('afterBegin'), { - initializeRange: function() { - this.range.selectNodeContents(this.element); - this.range.collapse(true); - }, - - insertContent: function(fragments) { - fragments.reverse(false).each((function(fragment) { - this.element.insertBefore(fragment, this.element.firstChild); - }).bind(this)); - } -}); - -Insertion.Bottom = Class.create(); -Insertion.Bottom.prototype = Object.extend(new Abstract.Insertion('beforeEnd'), { - initializeRange: function() { - this.range.selectNodeContents(this.element); - this.range.collapse(this.element); - }, - - insertContent: function(fragments) { - fragments.each((function(fragment) { - this.element.appendChild(fragment); - }).bind(this)); - } -}); - -Insertion.After = Class.create(); -Insertion.After.prototype = Object.extend(new Abstract.Insertion('afterEnd'), { - initializeRange: function() { - this.range.setStartAfter(this.element); - }, - - insertContent: function(fragments) { - fragments.each((function(fragment) { - this.element.parentNode.insertBefore(fragment, - this.element.nextSibling); - }).bind(this)); - } -}); - -/*--------------------------------------------------------------------------*/ - -Element.ClassNames = Class.create(); -Element.ClassNames.prototype = { - initialize: function(element) { - this.element = $(element); - }, - - _each: function(iterator) { - this.element.className.split(/\s+/).select(function(name) { - return name.length > 0; - })._each(iterator); - }, - - set: function(className) { - this.element.className = className; - }, - - add: function(classNameToAdd) { - if (this.include(classNameToAdd)) return; - this.set(this.toArray().concat(classNameToAdd).join(' ')); - }, - - remove: function(classNameToRemove) { - if (!this.include(classNameToRemove)) return; - this.set(this.select(function(className) { - return className != classNameToRemove; - }).join(' ')); - }, - - toString: function() { - return this.toArray().join(' '); - } -} - -Object.extend(Element.ClassNames.prototype, Enumerable); -var Field = { - clear: function() { - for (var i = 0; i < arguments.length; i++) - $(arguments[i]).value = ''; - }, - - focus: function(element) { - $(element).focus(); - }, - - present: function() { - for (var i = 0; i < arguments.length; i++) - if ($(arguments[i]).value == '') return false; - return true; - }, - - select: function(element) { - $(element).select(); - }, - - activate: function(element) { - element = $(element); - element.focus(); - if (element.select) - element.select(); - } -} - -/*--------------------------------------------------------------------------*/ - -var Form = { - serialize: function(form) { - var elements = Form.getElements($(form)); - var queryComponents = new Array(); - - for (var i = 0; i < elements.length; i++) { - var queryComponent = Form.Element.serialize(elements[i]); - if (queryComponent) - queryComponents.push(queryComponent); - } - - return queryComponents.join('&'); - }, - - getElements: function(form) { - form = $(form); - var elements = new Array(); - - for (tagName in Form.Element.Serializers) { - var tagElements = form.getElementsByTagName(tagName); - for (var j = 0; j < tagElements.length; j++) - elements.push(tagElements[j]); - } - return elements; - }, - - getInputs: function(form, typeName, name) { - form = $(form); - var inputs = form.getElementsByTagName('input'); - - if (!typeName && !name) - return inputs; - - var matchingInputs = new Array(); - for (var i = 0; i < inputs.length; i++) { - var input = inputs[i]; - if ((typeName && input.type != typeName) || - (name && input.name != name)) - continue; - matchingInputs.push(input); - } - - return matchingInputs; - }, - - disable: function(form) { - var elements = Form.getElements(form); - for (var i = 0; i < elements.length; i++) { - var element = elements[i]; - element.blur(); - element.disabled = 'true'; - } - }, - - enable: function(form) { - var elements = Form.getElements(form); - for (var i = 0; i < elements.length; i++) { - var element = elements[i]; - element.disabled = ''; - } - }, - - findFirstElement: function(form) { - return Form.getElements(form).find(function(element) { - return element.type != 'hidden' && !element.disabled && - ['input', 'select', 'textarea'].include(element.tagName.toLowerCase()); - }); - }, - - focusFirstElement: function(form) { - Field.activate(Form.findFirstElement(form)); - }, - - reset: function(form) { - $(form).reset(); - } -} - -Form.Element = { - serialize: function(element) { - element = $(element); - var method = element.tagName.toLowerCase(); - var parameter = Form.Element.Serializers[method](element); - - if (parameter) { - var key = encodeURIComponent(parameter[0]); - if (key.length == 0) return; - - if (parameter[1].constructor != Array) - parameter[1] = [parameter[1]]; - - return parameter[1].map(function(value) { - return key + '=' + encodeURIComponent(value); - }).join('&'); - } - }, - - getValue: function(element) { - element = $(element); - var method = element.tagName.toLowerCase(); - var parameter = Form.Element.Serializers[method](element); - - if (parameter) - return parameter[1]; - } -} - -Form.Element.Serializers = { - input: function(element) { - switch (element.type.toLowerCase()) { - case 'submit': - case 'hidden': - case 'password': - case 'text': - return Form.Element.Serializers.textarea(element); - case 'checkbox': - case 'radio': - return Form.Element.Serializers.inputSelector(element); - } - return false; - }, - - inputSelector: function(element) { - if (element.checked) - return [element.name, element.value]; - }, - - textarea: function(element) { - return [element.name, element.value]; - }, - - select: function(element) { - return Form.Element.Serializers[element.type == 'select-one' ? - 'selectOne' : 'selectMany'](element); - }, - - selectOne: function(element) { - var value = '', opt, index = element.selectedIndex; - if (index >= 0) { - opt = element.options[index]; - value = opt.value; - if (!value && !('value' in opt)) - value = opt.text; - } - return [element.name, value]; - }, - - selectMany: function(element) { - var value = new Array(); - for (var i = 0; i < element.length; i++) { - var opt = element.options[i]; - if (opt.selected) { - var optValue = opt.value; - if (!optValue && !('value' in opt)) - optValue = opt.text; - value.push(optValue); - } - } - return [element.name, value]; - } -} - -/*--------------------------------------------------------------------------*/ - -var $F = Form.Element.getValue; - -/*--------------------------------------------------------------------------*/ - -Abstract.TimedObserver = function() {} -Abstract.TimedObserver.prototype = { - initialize: function(element, frequency, callback) { - this.frequency = frequency; - this.element = $(element); - this.callback = callback; - - this.lastValue = this.getValue(); - this.registerCallback(); - }, - - registerCallback: function() { - setInterval(this.onTimerEvent.bind(this), this.frequency * 1000); - }, - - onTimerEvent: function() { - var value = this.getValue(); - if (this.lastValue != value) { - this.callback(this.element, value); - this.lastValue = value; - } - } -} - -Form.Element.Observer = Class.create(); -Form.Element.Observer.prototype = Object.extend(new Abstract.TimedObserver(), { - getValue: function() { - return Form.Element.getValue(this.element); - } -}); - -Form.Observer = Class.create(); -Form.Observer.prototype = Object.extend(new Abstract.TimedObserver(), { - getValue: function() { - return Form.serialize(this.element); - } -}); - -/*--------------------------------------------------------------------------*/ - -Abstract.EventObserver = function() {} -Abstract.EventObserver.prototype = { - initialize: function(element, callback) { - this.element = $(element); - this.callback = callback; - - this.lastValue = this.getValue(); - if (this.element.tagName.toLowerCase() == 'form') - this.registerFormCallbacks(); - else - this.registerCallback(this.element); - }, - - onElementEvent: function() { - var value = this.getValue(); - if (this.lastValue != value) { - this.callback(this.element, value); - this.lastValue = value; - } - }, - - registerFormCallbacks: function() { - var elements = Form.getElements(this.element); - for (var i = 0; i < elements.length; i++) - this.registerCallback(elements[i]); - }, - - registerCallback: function(element) { - if (element.type) { - switch (element.type.toLowerCase()) { - case 'checkbox': - case 'radio': - Event.observe(element, 'click', this.onElementEvent.bind(this)); - break; - case 'password': - case 'text': - case 'textarea': - case 'select-one': - case 'select-multiple': - Event.observe(element, 'change', this.onElementEvent.bind(this)); - break; - } - } - } -} - -Form.Element.EventObserver = Class.create(); -Form.Element.EventObserver.prototype = Object.extend(new Abstract.EventObserver(), { - getValue: function() { - return Form.Element.getValue(this.element); - } -}); - -Form.EventObserver = Class.create(); -Form.EventObserver.prototype = Object.extend(new Abstract.EventObserver(), { - getValue: function() { - return Form.serialize(this.element); - } -}); -if (!window.Event) { - var Event = new Object(); -} - -Object.extend(Event, { - KEY_BACKSPACE: 8, - KEY_TAB: 9, - KEY_RETURN: 13, - KEY_ESC: 27, - KEY_LEFT: 37, - KEY_UP: 38, - KEY_RIGHT: 39, - KEY_DOWN: 40, - KEY_DELETE: 46, - - element: function(event) { - return event.target || event.srcElement; - }, - - isLeftClick: function(event) { - return (((event.which) && (event.which == 1)) || - ((event.button) && (event.button == 1))); - }, - - pointerX: function(event) { - return event.pageX || (event.clientX + - (document.documentElement.scrollLeft || document.body.scrollLeft)); - }, - - pointerY: function(event) { - return event.pageY || (event.clientY + - (document.documentElement.scrollTop || document.body.scrollTop)); - }, - - stop: function(event) { - if (event.preventDefault) { - event.preventDefault(); - event.stopPropagation(); - } else { - event.returnValue = false; - event.cancelBubble = true; - } - }, - - // find the first node with the given tagName, starting from the - // node the event was triggered on; traverses the DOM upwards - findElement: function(event, tagName) { - var element = Event.element(event); - while (element.parentNode && (!element.tagName || - (element.tagName.toUpperCase() != tagName.toUpperCase()))) - element = element.parentNode; - return element; - }, - - observers: false, - - _observeAndCache: function(element, name, observer, useCapture) { - if (!this.observers) this.observers = []; - if (element.addEventListener) { - this.observers.push([element, name, observer, useCapture]); - element.addEventListener(name, observer, useCapture); - } else if (element.attachEvent) { - this.observers.push([element, name, observer, useCapture]); - element.attachEvent('on' + name, observer); - } - }, - - unloadCache: function() { - if (!Event.observers) return; - for (var i = 0; i < Event.observers.length; i++) { - Event.stopObserving.apply(this, Event.observers[i]); - Event.observers[i][0] = null; - } - Event.observers = false; - }, - - observe: function(element, name, observer, useCapture) { - var element = $(element); - useCapture = useCapture || false; - - if (name == 'keypress' && - (navigator.appVersion.match(/Konqueror|Safari|KHTML/) - || element.attachEvent)) - name = 'keydown'; - - this._observeAndCache(element, name, observer, useCapture); - }, - - stopObserving: function(element, name, observer, useCapture) { - var element = $(element); - useCapture = useCapture || false; - - if (name == 'keypress' && - (navigator.appVersion.match(/Konqueror|Safari|KHTML/) - || element.detachEvent)) - name = 'keydown'; - - if (element.removeEventListener) { - element.removeEventListener(name, observer, useCapture); - } else if (element.detachEvent) { - element.detachEvent('on' + name, observer); - } - } -}); - -/* prevent memory leaks in IE */ -Event.observe(window, 'unload', Event.unloadCache, false); -var Position = { - // set to true if needed, warning: firefox performance problems - // NOT neeeded for page scrolling, only if draggable contained in - // scrollable elements - includeScrollOffsets: false, - - // must be called before calling withinIncludingScrolloffset, every time the - // page is scrolled - prepare: function() { - this.deltaX = window.pageXOffset - || document.documentElement.scrollLeft - || document.body.scrollLeft - || 0; - this.deltaY = window.pageYOffset - || document.documentElement.scrollTop - || document.body.scrollTop - || 0; - }, - - realOffset: function(element) { - var valueT = 0, valueL = 0; - do { - valueT += element.scrollTop || 0; - valueL += element.scrollLeft || 0; - element = element.parentNode; - } while (element); - return [valueL, valueT]; - }, - - cumulativeOffset: function(element) { - var valueT = 0, valueL = 0; - do { - valueT += element.offsetTop || 0; - valueL += element.offsetLeft || 0; - element = element.offsetParent; - } while (element); - return [valueL, valueT]; - }, - - positionedOffset: function(element) { - var valueT = 0, valueL = 0; - do { - valueT += element.offsetTop || 0; - valueL += element.offsetLeft || 0; - element = element.offsetParent; - if (element) { - p = Element.getStyle(element, 'position'); - if (p == 'relative' || p == 'absolute') break; - } - } while (element); - return [valueL, valueT]; - }, - - offsetParent: function(element) { - if (element.offsetParent) return element.offsetParent; - if (element == document.body) return element; - - while ((element = element.parentNode) && element != document.body) - if (Element.getStyle(element, 'position') != 'static') - return element; - - return document.body; - }, - - // caches x/y coordinate pair to use with overlap - within: function(element, x, y) { - if (this.includeScrollOffsets) - return this.withinIncludingScrolloffsets(element, x, y); - this.xcomp = x; - this.ycomp = y; - this.offset = this.cumulativeOffset(element); - - return (y >= this.offset[1] && - y < this.offset[1] + element.offsetHeight && - x >= this.offset[0] && - x < this.offset[0] + element.offsetWidth); - }, - - withinIncludingScrolloffsets: function(element, x, y) { - var offsetcache = this.realOffset(element); - - this.xcomp = x + offsetcache[0] - this.deltaX; - this.ycomp = y + offsetcache[1] - this.deltaY; - this.offset = this.cumulativeOffset(element); - - return (this.ycomp >= this.offset[1] && - this.ycomp < this.offset[1] + element.offsetHeight && - this.xcomp >= this.offset[0] && - this.xcomp < this.offset[0] + element.offsetWidth); - }, - - // within must be called directly before - overlap: function(mode, element) { - if (!mode) return 0; - if (mode == 'vertical') - return ((this.offset[1] + element.offsetHeight) - this.ycomp) / - element.offsetHeight; - if (mode == 'horizontal') - return ((this.offset[0] + element.offsetWidth) - this.xcomp) / - element.offsetWidth; - }, - - clone: function(source, target) { - source = $(source); - target = $(target); - target.style.position = 'absolute'; - var offsets = this.cumulativeOffset(source); - target.style.top = offsets[1] + 'px'; - target.style.left = offsets[0] + 'px'; - target.style.width = source.offsetWidth + 'px'; - target.style.height = source.offsetHeight + 'px'; - }, - - page: function(forElement) { - var valueT = 0, valueL = 0; - - var element = forElement; - do { - valueT += element.offsetTop || 0; - valueL += element.offsetLeft || 0; - - // Safari fix - if (element.offsetParent==document.body) - if (Element.getStyle(element,'position')=='absolute') break; - - } while (element = element.offsetParent); - - element = forElement; - do { - valueT -= element.scrollTop || 0; - valueL -= element.scrollLeft || 0; - } while (element = element.parentNode); - - return [valueL, valueT]; - }, - - clone: function(source, target) { - var options = Object.extend({ - setLeft: true, - setTop: true, - setWidth: true, - setHeight: true, - offsetTop: 0, - offsetLeft: 0 - }, arguments[2] || {}) - - // find page position of source - source = $(source); - var p = Position.page(source); - - // find coordinate system to use - target = $(target); - var delta = [0, 0]; - var parent = null; - // delta [0,0] will do fine with position: fixed elements, - // position:absolute needs offsetParent deltas - if (Element.getStyle(target,'position') == 'absolute') { - parent = Position.offsetParent(target); - delta = Position.page(parent); - } - - // correct by body offsets (fixes Safari) - if (parent == document.body) { - delta[0] -= document.body.offsetLeft; - delta[1] -= document.body.offsetTop; - } - - // set position - if(options.setLeft) target.style.left = (p[0] - delta[0] + options.offsetLeft) + 'px'; - if(options.setTop) target.style.top = (p[1] - delta[1] + options.offsetTop) + 'px'; - if(options.setWidth) target.style.width = source.offsetWidth + 'px'; - if(options.setHeight) target.style.height = source.offsetHeight + 'px'; - }, - - absolutize: function(element) { - element = $(element); - if (element.style.position == 'absolute') return; - Position.prepare(); - - var offsets = Position.positionedOffset(element); - var top = offsets[1]; - var left = offsets[0]; - var width = element.clientWidth; - var height = element.clientHeight; - - element._originalLeft = left - parseFloat(element.style.left || 0); - element._originalTop = top - parseFloat(element.style.top || 0); - element._originalWidth = element.style.width; - element._originalHeight = element.style.height; - - element.style.position = 'absolute'; - element.style.top = top + 'px';; - element.style.left = left + 'px';; - element.style.width = width + 'px';; - element.style.height = height + 'px';; - }, - - relativize: function(element) { - element = $(element); - if (element.style.position == 'relative') return; - Position.prepare(); - - element.style.position = 'relative'; - var top = parseFloat(element.style.top || 0) - (element._originalTop || 0); - var left = parseFloat(element.style.left || 0) - (element._originalLeft || 0); - - element.style.top = top + 'px'; - element.style.left = left + 'px'; - element.style.height = element._originalHeight; - element.style.width = element._originalWidth; - } -} - -// Safari returns margins on body which is incorrect if the child is absolutely -// positioned. For performance reasons, redefine Position.cumulativeOffset for -// KHTML/WebKit only. -if (/Konqueror|Safari|KHTML/.test(navigator.userAgent)) { - Position.cumulativeOffset = function(element) { - var valueT = 0, valueL = 0; - do { - valueT += element.offsetTop || 0; - valueL += element.offsetLeft || 0; - if (element.offsetParent == document.body) - if (Element.getStyle(element, 'position') == 'absolute') break; - - element = element.offsetParent; - } while (element); - - return [valueL, valueT]; - } -} \ No newline at end of file Modified: slashjp/branches/upstream/current/plugins/Ajax/htdocs/images/sd_autocomplete.js =================================================================== --- slashjp/branches/upstream/current/plugins/Ajax/htdocs/images/sd_autocomplete.js 2008-03-31 12:09:17 UTC (rev 559) +++ slashjp/branches/upstream/current/plugins/Ajax/htdocs/images/sd_autocomplete.js 2008-04-01 03:35:14 UTC (rev 560) @@ -1,5 +1,5 @@ // _*_ Mode: JavaScript; tab-width: 8; indent-tabs-mode: true _*_ -// $Id: sd_autocomplete.js,v 1.47 2008/01/24 19:51:02 pudge Exp $ +// $Id: sd_autocomplete.js,v 1.50 2008/03/11 16:38:18 scc Exp $ YAHOO.namespace("slashdot"); @@ -79,6 +79,7 @@ "books", "bsd", "developers", +"entertainment", "features", "games", "hardware", @@ -86,12 +87,14 @@ "it", "linux", "mainpage", +"news", "politics", "polls", "radio", "science", "search", "tacohell", +"technology", "vendors", "vendor_amd", "yro" ]; @@ -126,7 +129,6 @@ "links", "movies", "money", -"news", "pilot", "starwars", "sun", @@ -201,7 +203,6 @@ "osnine", "osx", "portables", -"technology", "utilities", "wireless", "portables", @@ -380,9 +381,9 @@ this._completer.autoHighlight = false; - // widget must be visible to move + // widget must be visible to move YAHOO.util.Dom.removeClass(this._widget, "hidden"); - // move widget to be near the 'source' + // move widget to be near the 'source' var pos = YAHOO.util.Dom.getXY(this._sourceEl); pos[1] += this._sourceEl.offsetHeight; YAHOO.util.Dom.setXY(this._widget, pos); @@ -394,7 +395,7 @@ YAHOO.util.Dom.removeClass(this._spareInput, "hidden"); this._spareInput.value = ""; this._spareInput.focus(); - this._pending_hide = setTimeout("YAHOO.slashdot.gCompleterWidget._hide()", 15000); + this._pending_hide = setTimeout(YAHOO.slashdot.gCompleterWidget._hide, 15000); } else YAHOO.util.Dom.addClass(this._spareInput, "hidden"); @@ -507,9 +508,9 @@ me._hide(); break; case 13: - // I'm sorry to say we have to test first, something somehow somewhere can still leave - // leave this listener dangling; want to look deeper into this, as this would _still_ - // leave the listener dangling + // I'm sorry to say we have to test first, something somehow somewhere can still + // leave this listener dangling; want to look deeper into this, as this would _still_ + // leave the listener dangling if ( me._completer ) me._completer.unmatchedItemSelectEvent.fire(me._completer, me, me._completer._sCurQuery); break; @@ -517,6 +518,6 @@ if ( me._pending_hide ) clearTimeout(me._pending_hide); if ( me._needsSpareInput() ) - me._pending_hide = setTimeout("YAHOO.slashdot.gCompleterWidget._hide()", 15000); + me._pending_hide = setTimeout(YAHOO.slashdot.gCompleterWidget._hide, 15000); } } Modified: slashjp/branches/upstream/current/plugins/Ajax/htdocs/images/sectionprefs.js =================================================================== --- slashjp/branches/upstream/current/plugins/Ajax/htdocs/images/sectionprefs.js 2008-03-31 12:09:17 UTC (rev 559) +++ slashjp/branches/upstream/current/plugins/Ajax/htdocs/images/sectionprefs.js 2008-04-01 03:35:14 UTC (rev 560) @@ -1,4 +1,4 @@ -// $Id: sectionprefs.js,v 1.8 2007/11/29 19:06:20 entweichen Exp $ +// $Id: sectionprefs.js,v 1.10 2008/03/14 18:45:51 scc Exp $ function configSectionPopup() { var title = "<a href=\"#\" onclick=\"window.location.reload()\" style=\"color:#fff;\">Sectional Display Prefs</a> "; @@ -7,7 +7,7 @@ createPopup(getXYForId('links-sections-title'), title, "sectionprefs", "", "Loading..."); var url = 'ajax.pl'; - var params = []; + var params = {}; params['op'] = 'getSectionPrefsHTML'; ajax_update(params, 'sectionprefs-contents'); @@ -26,12 +26,11 @@ } function postSectionPrefChanges(el) { - var params = []; + var params = {}; params['op'] = 'setSectionNexusPrefs'; params[el.name] = el.value; - var h = $H(params); - var sec_pref_msg = $("sectionprefs-message"); + var sec_pref_msg = $dom("sectionprefs-message"); sec_pref_msg.innerHTML = "Saving..."; var url = 'ajax.pl'; ajax_update(params, 'sectionprefs-message'); Modified: slashjp/branches/upstream/current/plugins/Ajax/mysql_dump.sql =================================================================== --- slashjp/branches/upstream/current/plugins/Ajax/mysql_dump.sql 2008-03-31 12:09:17 UTC (rev 559) +++ slashjp/branches/upstream/current/plugins/Ajax/mysql_dump.sql 2008-04-01 03:35:14 UTC (rev 560) @@ -1,5 +1,5 @@ # -# $Id: mysql_dump.sql,v 1.25 2007/12/12 22:35:19 tvroom Exp $ +# $Id: mysql_dump.sql,v 1.26 2008/03/18 16:26:16 tvroom Exp $ # INSERT INTO reskey_resources VALUES (100, 'ajax_base', 'no'); @@ -155,7 +155,7 @@ INSERT INTO ajax_ops VALUES (NULL, 'remarks_config_save', 'Slash::Remarks', 'ajaxConfigSave', 'ajax_admin', 'createuse'); # signoff -INSERT INTO ajax_ops VALUES (NULL, 'admin_signoff', 'Slash::Admin', 'ajax_signoff', 'ajax_admin', 'use'); +INSERT INTO ajax_ops VALUES (NULL, 'admin_signoff', 'Slash::Admin', 'ajax_signoff', 'ajax_user_static', 'createuse'); # slashboxes INSERT INTO ajax_ops VALUES (NULL, 'admin_slashdbox', 'Slash::Admin', 'ajax_slashdbox', 'ajax_admin', 'createuse'); Modified: slashjp/branches/upstream/current/plugins/Ajax/templates/edit_comment;ajax;default =================================================================== --- slashjp/branches/upstream/current/plugins/Ajax/templates/edit_comment;ajax;default 2008-03-31 12:09:17 UTC (rev 559) +++ slashjp/branches/upstream/current/plugins/Ajax/templates/edit_comment;ajax;default 2008-04-01 03:35:14 UTC (rev 560) @@ -20,16 +20,16 @@ edit_comment __template__ <div id="wide"> -[% IF pid %] - [% PROCESS titlebar title="Reply to: $reply.subject" %] -[% ELSE %] - [% PROCESS titlebar title="Reply to: XXXXX" %] -[% END %] +[% this_title = pid ? reply.subject : discussion.title; + this_title = this_title | strip_html; + PROCESS titlebar title="Reply to: $this_title" %] +<p>If you have difficulty with this form, please use the <a href="[% gSkin.rootdir %]/comments.pl?op=Reply&sid=[% sid %]&pid=[% pid %]">old form</a>.</p> + [% IF user.is_anon %]<p> [% IF constants.allow_anonymous %] You are not logged in. You can <a href=\"${gSkin.rootdir}/login.pl\">log -in now</a>, or <a href="[% gSkin.rootdir %]/users.pl">Create an Account</a>/ +in now</a>, or <a href="[% gSkin.rootdir %]/users.pl">Create an Account</a>. [% ELSE %] You are not logged in. You can <a href=\"${gSkin.rootdir}/login.pl\">log in now</a>, <a href="[% gSkin.rootdir %]/users.pl">Create an Account</a>, @@ -43,22 +43,28 @@ <div id="replyto_reply_[% pid %]" class="replyto_reply"> <input type="hidden" name="sid" value="[% sid %]"> [% IF pid %]<input type="hidden" name="pid" value="[% pid %]">[% END %] -[% IF gotmodwarning %]<input type="hidden" name="gotmodwarning" value="1">[% END # XXXXX %] +<input type="hidden" name="gotmodwarning_[% pid %]" id="gotmodwarning_[% pid %]" value="0"> [% reskey_label = "reskey_reply_$pid"; PROCESS reskey_tag %] -<p><input type="text" name="postersubj_[% pid %]" id="postersubj_[% pid %]" value="Re:[% reply.subject | strip_attribute %]" size="50" maxlength="50"> -[<a href="[% gSkin.rootdir %]/my/comments" onclick="getModalPrefs('d2_posting', 'Discussion 2'); return false;">Customize Posting Preferences</a>]</p> +<p><input type="text" name="postersubj_[% pid %]" id="postersubj_[% pid %]" value="[% form.postersubj | strip_attribute %]" size="50" maxlength="50"> +[% UNLESS user.is_anon %][<a href="[% gSkin.rootdir %]/my/comments" onclick="getModalPrefs('d2_posting', 'Discussion 2'); return false;">Options</a>] +[%- IF constants.allow_anonymous && user.karma > -1 && (discussion.commentstatus == 'enabled' || discussion.commentstatus == 'logged_in') -%] + <input type="checkbox" name="postanon_[% pid %]" id="postanon_[% pid %]"> Post Anonymously +[%- END %]</p>[% END %] <p><textarea wrap="virtual" name="postercomment_[% pid %]" id="postercomment_[% pid %]" rows="[% user.textarea_rows || constants.textarea_rows %]" cols="[% user.textarea_cols || constants.textarea_cols %]"></textarea></p> -[% IF constants.allow_anonymous && user.karma > -1 && !user.is_anon && (discussion.commentstatus == 'enabled' || discussion.commentstatus == 'logged_in') %] - <p><input type="checkbox" name="postanon"> Post Anonymously</p> -[% END %] - </div> <div id="replyto_msg_[% pid %]" class="replyto_msg"></div> - <div id="replyto_buttons_[% pid %]" class="replyto_buttons"> -<input type="button" name="preview_[% pid %]" id="preview_[% pid %]" value="Preview" class="button" onclick="previewReply([% pid %]); return false;"> -<input type="button" name="submit_[% pid %]" id="submit_[% pid %]" value="Submit" class="button" onclick="fetchEl('preview_[% pid %]').style.display='inline'; fetchEl('submit_[% pid %]').style.display='none'; return false;" style="display: none"> -<input type="button" name="quotereply_[% pid %]" id="quotereply_[% pid %]" value="Quote" class="button" onclick="quoteReply([% pid %]); return false;"> + <div class="replyto_buttons"> + <span id="replyto_buttons_1_[% pid %]"> +<input type="button" name="preview_[% pid %]" id="preview_[% pid %]" value="Preview" class="button" onclick="previewReply([% pid %]); return false;"> +[%- IF pid # not for root-level reply %] +<input type="button" name="quotereply_[% pid %]" id="quotereply_[% pid %]" value="Quote Parent" class="button" onclick="quoteReply([% pid %]); return false;">[% END %] + </span><span id="replyto_buttons_2_[% pid %]" style="display: none"> +<input type="button" name="submit_[% pid %]" id="submit_[% pid %]" value="Submit" class="button" onclick="submitReply([% pid %]); return false;"> +<input type="button" name="edit_[% pid %]" id="edit_[% pid %]" value="Continue Editing" class="button" onclick="editReply([% pid %]); return false;"> + </span><span id="replyto_buttons_3_[% pid %]"> +<input type="button" name="cancel_[% pid %]" id="cancel_[% pid %]" value="Cancel" class="button" onclick="cancelReply([% pid %]); return false;"> + </span> </div> </form> [% END # IF !user.is_anon || constants.allow_anonymous %] @@ -67,4 +73,4 @@ __seclev__ 1000 __version__ -$Id: edit_comment;ajax;default,v 1.1 2008/02/28 21:39:31 pudge Exp $ +$Id: edit_comment;ajax;default,v 1.5 2008/03/19 08:25:31 pudge Exp $ Modified: slashjp/branches/upstream/current/plugins/Ajax/templates/prefs_d2;ajax;default =================================================================== --- slashjp/branches/upstream/current/plugins/Ajax/templates/prefs_d2;ajax;default 2008-03-31 12:09:17 UTC (rev 559) +++ slashjp/branches/upstream/current/plugins/Ajax/templates/prefs_d2;ajax;default 2008-04-01 03:35:14 UTC (rev 560) @@ -42,7 +42,6 @@ <br> [% IF user.discussion2 && user.discussion2 == "slashdot" %] - <blockquote> <div> Retrieve [% comment_q_name = (user.is_subscriber || user.is_admin) ? 'd2_comment_q_all' : 'd2_comment_q'; comment_q = Slash.db.getDescriptions(comment_q_name); @@ -54,7 +53,6 @@ comment_order_def = user.d2_comment_order || 0; # score Slash.createSelect('d2_comment_order', comment_order, comment_order_def, 1) %] Comments First </div> - </blockquote> [% END %] <div id="modalprefhelp_sortorder" class="modalprefhelp" style="display: none;"> @@ -97,11 +95,11 @@ Show the actual domain of any link in brackets. </div> - <blockquote><div> + <div> <input type="radio" name="domaintags" [% domaintags.0 %] value=0> Never show link domains<br> <input type="radio" name="domaintags" [% domaintags.1 %] value=1> Show the links domain only in recommended situations<br> <input type="radio" name="domaintags" [% domaintags.2 %] value=2> Always show link domains - </div></blockquote> + </div> </td> </tr> @@ -112,4 +110,4 @@ __seclev__ 500 __version__ -$Id: prefs_d2;ajax;default,v 1.12 2008/02/28 17:03:12 entweichen Exp $ +$Id: prefs_d2;ajax;default,v 1.13 2008/03/12 14:14:59 entweichen Exp $ Modified: slashjp/branches/upstream/current/plugins/Email/templates/dispStory;email;default =================================================================== --- slashjp/branches/upstream/current/plugins/Email/templates/dispStory;email;default 2008-03-31 12:09:17 UTC (rev 559) +++ slashjp/branches/upstream/current/plugins/Email/templates/dispStory;email;default 2008-04-01 03:35:14 UTC (rev 560) @@ -56,7 +56,7 @@ To opt-out of further emailings: [% thisurl %]/email.pl?op=optout_form -Copyright 1997-2005 [% constants.sitepublisher %]. All rights reserved. +Copyright 1997-2008 [% constants.sitepublisher %]. All rights reserved. __version__ -$Id: dispStory;email;default,v 1.9 2005/03/30 23:41:45 pudge Exp $ +$Id: dispStory;email;default,v 1.10 2008/03/13 14:22:37 entweichen Exp $ Modified: slashjp/branches/upstream/current/plugins/FAQSlashdot/faq/friends.shtml =================================================================== --- slashjp/branches/upstream/current/plugins/FAQSlashdot/faq/friends.shtml 2008-03-31 12:09:17 UTC (rev 559) +++ slashjp/branches/upstream/current/plugins/FAQSlashdot/faq/friends.shtml 2008-04-01 03:35:14 UTC (rev 560) @@ -3,18 +3,25 @@ <html> <head> <title>Slashdot FAQ - Friends and Journals</title> -<!-- $Id: friends.shtml,v 1.7 2005/10/11 02:32:13 tvroom Exp $ --> +<!-- $Id: friends.shtml,v 1.8 2008/03/12 14:08:32 entweichen Exp $ --> <!--#include virtual="/slashcssbase.inc"--> <!--#include virtual="/slashhead-gen-full.inc"--> - <ul class="menu"> - <li><a href="accounts.shtml">Previous section</a></li> - <li><a href="subscriptions.shtml">Next section</a></li> - <li><a href="index.shtml">Index</a></li> - </ul> - - <hr> + <div class="generaltitle"> + <div class="title"> + <h3>Friends and Journals</h3> + </div> + </div> + <div id="usermenu"> + <ul class="menu" style="padding: 5px 10px 5px 10px;"> + <li><span class="begin"><a href="/help" class="begin">Return to Help & Preferences</a></span></li> + <li><span class="begin"><a href="/faq" class="begin">Return to the FAQ</a></span></li> + <li><span class="begin"><a href="accounts.shtml" class="begin">Previous Section</a></span></li> + <li><span class="begin"><a href="subscriptions.shtml" class="begin">Next Section</a></span></li> + </ul> + </div> + <h2><a name="fj100" id="fj100">Where is my journal?</a></h2> <p><em>Your</em> journal can be found at <a href="http://slashdot.org/my/journal">http://slashdot.org/my/journal</a>.</p> <p><em><small> Modified: slashjp/branches/upstream/current/plugins/FireHose/FireHose.pm =================================================================== --- slashjp/branches/upstream/current/plugins/FireHose/FireHose.pm 2008-03-31 12:09:17 UTC (rev 559) +++ slashjp/branches/upstream/current/plugins/FireHose/FireHose.pm 2008-04-01 03:35:14 UTC (rev 560) @@ -1,7 +1,7 @@ # This code is a part of Slash, and is released under the GPL. # Copyright 1997-2005 by Open Source Technology Group. See README # and COPYING for more information, or see http://slashcode.com/. -# $Id: FireHose.pm,v 1.223 2008/02/27 02:37:05 tvroom Exp $ +# $Id: FireHose.pm,v 1.226 2008/03/18 16:16:02 tvroom Exp $ package Slash::FireHose; @@ -41,7 +41,7 @@ use base 'Slash::DB::MySQL'; use vars qw($VERSION); -($VERSION) = ' $Revision: 1.223 $ ' =~ /\$Revision:\s+([^\s]+)/; +($VERSION) = ' $Revision: 1.226 $ ' =~ /\$Revision:\s+([^\s]+)/; sub createFireHose { my($self, $data) = @_; $data->{dept} ||= ""; @@ -561,7 +561,7 @@ push @where, "popularity >= $pop_q"; } } - if ($user->{is_admin}) { + if ($user->{is_admin} || $user->{acl}{signoff_allowed}) { my $signoff_label = 'sign' . $user->{uid} . 'ed'; if ($options->{unsigned}) { @@ -1124,7 +1124,7 @@ my $newtagspreloadtext = join ' ', @newtagspreload; #print STDERR "ajaxGetUserFirehose $newtagspreloadtext\n\n"; - return slashDisplay('tagsfirehosedivuser', { + return slashDisplay($form->{nodnix} ? 'tagsnodnixuser' : 'tagsfirehosedivuser', { id => $id, newtagspreloadtext => $newtagspreloadtext, }, { Return => 1 }); @@ -1516,9 +1516,13 @@ } +# Return a positive number if data was altered, 0 if it was not, +# or undef on error. + sub setFireHose { my($self, $id, $data) = @_; - return unless $id && $data; + return undef unless $id && $data; + return 0 if !%$data; my $id_q = $self->sqlQuote($id); my $mcd = $self->getMCD(); @@ -1547,7 +1551,7 @@ $self->setGlobjAdminnote($globjid, $note); } - return if !keys %$data; + return 0 if !keys %$data; my $text_data = {}; @@ -1556,9 +1560,11 @@ $text_data->{bodytext} = delete $data->{bodytext} if exists $data->{bodytext}; $text_data->{media} = delete $data->{media} if exists $data->{media}; - $self->sqlUpdate('firehose', $data, "id=$id_q"); - $self->sqlUpdate('firehose_text', $text_data, "id=$id_q") if keys %$text_data; - + my $rows = $self->sqlUpdate('firehose', $data, "id=$id_q"); +#{ use Data::Dumper; my $dstr = Dumper($data); $dstr =~ s/\s+/ /g; print STDERR "setFireHose A rows=$rows for id=$id_q data: $dstr\n"; } + $rows += $self->sqlUpdate('firehose_text', $text_data, "id=$id_q") if keys %$text_data; +#{ use Data::Dumper; my $dstr = Dumper($text_data); $dstr =~ s/\s+/ /g; print STDERR "setFireHose B rows=$rows for id=$id_q data: $dstr\n"; } + if ($mcd) { $mcd->delete("$mcdkey:$id", 3); } @@ -1570,6 +1576,8 @@ # $status = 'deleted' if $data->{accepted} eq 'yes' || $data->{rejected} eq 'yes'; $searchtoo->storeRecords(firehose => $id, { $status => 1 }); } + + return $rows; } sub dispFireHose { @@ -1595,6 +1603,9 @@ return [] unless $item && $user->{is_admin}; my $subnotes_ref = []; my $sub_memory = $self->getSubmissionMemory(); + my $url = ""; + $url = $self->getUrl($item->{url_id}) if $item->{url_id}; + foreach my $memory (@$sub_memory) { my $match = $memory->{submatch}; @@ -1602,7 +1613,8 @@ $item->{name} =~ m/$match/i || $item->{title} =~ m/$match/i || $item->{ipid} =~ m/$match/i || - $item->{introtext} =~ m/$match/i) { + $item->{introtext} =~ m/$match/i || + $url =~ m/$match/i) { push @$subnotes_ref, $memory; } } @@ -2625,4 +2637,4 @@ =head1 VERSION -$Id: FireHose.pm,v 1.223 2008/02/27 02:37:05 tvroom Exp $ +$Id: FireHose.pm,v 1.226 2008/03/18 16:16:02 tvroom Exp $ Modified: slashjp/branches/upstream/current/plugins/FireHose/PLUGIN =================================================================== --- slashjp/branches/upstream/current/plugins/FireHose/PLUGIN 2008-03-31 12:09:17 UTC (rev 559) +++ slashjp/branches/upstream/current/plugins/FireHose/PLUGIN 2008-04-01 03:35:14 UTC (rev 560) @@ -1,4 +1,4 @@ -# $Id: PLUGIN,v 1.29 2008/02/19 14:45:30 scc Exp $ +# $Id: PLUGIN,v 1.30 2008/03/03 14:11:11 scc Exp $ name=FireHose description="FireHose" css=firehose.css @@ -32,6 +32,7 @@ template=templates/tagsfirehosedivadmin;misc;default template=templates/tagsfirehosedivtagbox;misc;default template=templates/tagsfirehosedivuser;misc;default +template=templates/tagsnodnixuser;misc;default task=firehose_reject_old.pl task=firehose_backend.pl task=firehose_get_thumbnails.pl Modified: slashjp/branches/upstream/current/plugins/FireHose/firehose.css =================================================================== --- slashjp/branches/upstream/current/plugins/FireHose/firehose.css 2008-03-31 12:09:17 UTC (rev 559) +++ slashjp/branches/upstream/current/plugins/FireHose/firehose.css 2008-04-01 03:35:14 UTC (rev 560) @@ -449,9 +449,15 @@ .embed #nod-user-tags, #console #nod-input {left: 63px !important;} .embed #nix-user-tags, #console #nix-input {left: 68px !important;} .embed #nodmenu ul, #console #nodmenu ul {margin: 0 0 0 43px; background: #222; opacity: .9; border: 1px solid #111;} -ol#nod-hardened, ol#nix-hardened, ol#nod-hardened li, ol#nix-hardened li {background: black !important;} -ol#nod-hardened, ol#nix-hardened {margin-left: 0 !important; padding-left: 0 !important;} +ol#nod-hardened, ol#nix-hardened, ol#nod-hardened li, ol#nix-hardened li {position: relative; background: black !important;} +ol#nod-hardened, ol#nix-hardened {margin-left: 0 !important; padding-left: 0 !important; cursor: pointer;} +.tag-actions {display: none; position: absolute; opacity: 0.6; top: -0.75em; right: 0; width: 1.5em; font-size: 120%; text-align: center; color: black; background-color: white; -moz-border-radius: 0.1em; -webkit-border-radius: 0.1em;} +a.not-tag, a.del-tag {text-decoration: none;} +li:hover .tag-actions {display: inline;} +li .tag-actions:hover {opacity: 0.9;} +li .tag-actions .not-tag:hover, li .tag-actions .del-tag:hover {color: red;} + .article .title, .article h3, .article .generaltitle {border: none !important} .article .generaltitle, #firehoselist .article .title, .article h3 {line-height: 170% !important;} .briefarticle .generaltitle, .briefarticle .title, .briefarticle h3 {line-height: 160% !important;} Modified: slashjp/branches/upstream/current/plugins/FireHose/templates/firehose_tags_top;misc;default =================================================================== --- slashjp/branches/upstream/current/plugins/FireHose/templates/firehose_tags_top;misc;default 2008-03-31 12:09:17 UTC (rev 559) +++ slashjp/branches/upstream/current/plugins/FireHose/templates/firehose_tags_top;misc;default 2008-04-01 03:35:14 UTC (rev 560) @@ -26,7 +26,7 @@ [%- END -%] [%- tags_seen.${parts.0} = 1 -%] [%- END -%] - [%- IF item.type == "story" -%][% IF user.is_admin %][% PROCESS signoff stoid=item.srcid fhid = item.id %][% END %][% END %] + [%- IF item.type == "story" -%][% IF user.is_admin || user.acl.signoff_allowed %][% PROCESS signoff stoid=item.srcid fhid = item.id %][% END %][% END %] [% IF item.type == "feed" && user.is_admin %] [% feed_user = Slash.db.getUser(item.uid, "nickname"); %] [% feed_user | strip_literal %] @@ -35,4 +35,4 @@ __seclev__ 10000 __version__ -$Id: firehose_tags_top;misc;default,v 1.22 2007/08/22 20:26:14 scc Exp $ +$Id: firehose_tags_top;misc;default,v 1.23 2008/03/18 16:16:02 tvroom Exp $ Added: slashjp/branches/upstream/current/plugins/FireHose/templates/tagsnodnixuser;misc;default =================================================================== --- slashjp/branches/upstream/current/plugins/FireHose/templates/tagsnodnixuser;misc;default (rev 0) +++ slashjp/branches/upstream/current/plugins/FireHose/templates/tagsnodnixuser;misc;default 2008-04-01 03:35:14 UTC (rev 560) @@ -0,0 +1,23 @@ +__section__ +default +__description__ +id = id +newtagspreloadtext = text to preload the newtags-# field with + +WARNING: keep the related string in nodnix.js in sync with the <li> expansion, below +__title__ + +__page__ +misc +__lang__ +en_US +__name__ +tagsnodnixuser +__template__ +[% FOREACH tag = newtagspreloadtext.split(' ') %] +<li>[% tag %]<span class="tag-actions"><a class="not-tag" onmousedown="nodnix_not_tag('[% tag %]'); return false" href="#">!</a> <a class="del-tag" onmousedown="nodnix_del_tag('[% tag %]'); return false" href="#">x</a></span></li> +[% END %] +__seclev__ +10000 +__version__ +$Id: tagsnodnixuser;misc;default,v 1.4 2008/03/03 20:54:00 scc Exp $ Modified: slashjp/branches/upstream/current/plugins/Messages/templates/dailyheadlines;messages;default =================================================================== --- slashjp/branches/upstream/current/plugins/Messages/templates/dailyheadlines;messages;default 2008-03-31 12:09:17 UTC (rev 559) +++ slashjp/branches/upstream/current/plugins/Messages/templates/dailyheadlines;messages;default 2008-04-01 03:35:14 UTC (rev 560) @@ -25,9 +25,9 @@ [% END %] -Copyright 1997-2007 [% constants.sitepublisher %]. All rights reserved. +Copyright 1997-2008 [% constants.sitepublisher %]. All rights reserved. __seclev__ 500 __version__ -$Id: dailyheadlines;messages;default,v 1.13 2007/01/02 18:35:59 cowboyneal Exp $ +$Id: dailyheadlines;messages;default,v 1.14 2008/03/13 14:13:18 entweichen Exp $ Modified: slashjp/branches/upstream/current/plugins/Messages/templates/dailynews;messages;default =================================================================== --- slashjp/branches/upstream/current/plugins/Messages/templates/dailynews;messages;default 2008-03-31 12:09:17 UTC (rev 559) +++ slashjp/branches/upstream/current/plugins/Messages/templates/dailynews;messages;default 2008-04-01 03:35:14 UTC (rev 560) @@ -52,9 +52,9 @@ [% END %] -Copyright 1997-2006 [% constants.sitepublisher %]. All rights reserved. +Copyright 1997-2008 [% constants.sitepublisher %]. All rights reserved. __seclev__ 500 __version__ -$Id: dailynews;messages;default,v 1.14 2006/01/25 16:11:42 cowboyneal Exp $ +$Id: dailynews;messages;default,v 1.15 2008/03/13 14:14:08 entweichen Exp $ Modified: slashjp/branches/upstream/current/plugins/Moderation/Moderation.pm =================================================================== --- slashjp/branches/upstream/current/plugins/Moderation/Moderation.pm 2008-03-31 12:09:17 UTC (rev 559) +++ slashjp/branches/upstream/current/plugins/Moderation/Moderation.pm 2008-04-01 03:35:14 UTC (rev 560) @@ -1,7 +1,7 @@ # This code is a part of Slash, and is released under the GPL. # Copyright 1997-2005 by Open Source Technology Group. See README # and COPYING for more information, or see http://slashcode.com/. -# $Id: Moderation.pm,v 1.4 2008/02/21 01:01:52 pudge Exp $ +# $Id: Moderation.pm,v 1.9 2008/03/19 08:25:31 pudge Exp $ package Slash::Moderation; @@ -17,7 +17,7 @@ use base 'Slash::DB::Utility'; use base 'Slash::DB::MySQL'; -($VERSION) = ' $Revision: 1.4 $ ' =~ /\$Revision:\s+([^\s]+)/; +($VERSION) = ' $Revision: 1.9 $ ' =~ /\$Revision:\s+([^\s]+)/; sub new { my($class, $user) = @_; @@ -91,10 +91,12 @@ $self->countUsers({ max => 1 }), $self->getReasons ); - $html->{$score} = "(Score:$points"; + $html->{$score} = "Score:$points"; + $html->{$score} = qq[<a href="#" onclick="getModalPrefs('modcommentlog', 'Moderation Comment Log', $cid); return false">$html->{$score}</a>] + if $constants->{modal_prefs_active} && !$user->{is_anon}; $html->{$score} .= ", $reasons->{$comment->{reason}}{name}" if $comment->{reason} && $reasons->{$comment->{reason}}; - $html->{$score} .= ")"; + $html->{$score} = "($html->{$score})"; my $ptstr = $user->{points} == 1 ? 'point' : 'points'; $html->{$select} = "Moderated '$reasons->{$reason}{name}.' $user->{points} $ptstr left."; Modified: slashjp/branches/upstream/current/plugins/Rating/Rating.pm =================================================================== --- slashjp/branches/upstream/current/plugins/Rating/Rating.pm 2008-03-31 12:09:17 UTC (rev 559) +++ slashjp/branches/upstream/current/plugins/Rating/Rating.pm 2008-04-01 03:35:14 UTC (rev 560) @@ -1,7 +1,7 @@ # This code is a part of Slash, and is released under the GPL. # Copyright 1997-2005 by Open Source Technology Group. See README # and COPYING for more information, or see http://slashcode.com/. -# $Id: Rating.pm,v 1.7 2005/03/11 19:58:12 pudge Exp $ +# $Id: Rating.pm,v 1.8 2008/03/19 08:25:31 pudge Exp $ package Slash::Rating; @@ -16,7 +16,7 @@ use base 'Slash::DB::Utility'; use base 'Slash::DB::MySQL'; -($VERSION) = ' $Revision: 1.7 $ ' =~ /\$Revision:\s+([^\s]+)/; +($VERSION) = ' $Revision: 1.8 $ ' =~ /\$Revision:\s+([^\s]+)/; #Right, this is not needed at the moment but will be in the near future sub new { @@ -52,13 +52,13 @@ my $extras; $extras = $slashdb->getNexusExtrasForChosen({$disc_skin->{nexus} => 1}, {content_type => "comment"}) if $disc_skin && $disc_skin->{nexus}; - return unless $extras; + return 0 unless $extras; foreach my $extra(@$extras) { $can_create_vote=1 if $extra->[1] eq "comment_vote"; } - return unless $can_create_vote; + return 0 unless $can_create_vote; my $active = "yes"; my $val = 0; Modified: slashjp/branches/upstream/current/plugins/ResKey/mysql_dump.sql =================================================================== --- slashjp/branches/upstream/current/plugins/ResKey/mysql_dump.sql 2008-03-31 12:09:17 UTC (rev 559) +++ slashjp/branches/upstream/current/plugins/ResKey/mysql_dump.sql 2008-04-01 03:35:14 UTC (rev 560) @@ -1,5 +1,5 @@ # -# $Id: mysql_dump.sql,v 1.20 2007/11/01 20:35:19 jamiemccarthy Exp $ +# $Id: mysql_dump.sql,v 1.21 2008/03/19 21:09:47 pudge Exp $ # ### NOTE: reserved reskey IDs: @@ -54,7 +54,7 @@ INSERT INTO reskey_resource_checks VALUES (NULL, 1, 'all', 'Slash::ResKey::Checks::AL2::NoPost', 501); INSERT INTO reskey_resource_checks VALUES (NULL, 1, 'all', 'Slash::ResKey::Checks::AL2::Spammer', 531); INSERT INTO reskey_resource_checks VALUES (NULL, 1, 'all', 'Slash::ResKey::Checks::Duration', 601); -INSERT INTO reskey_resource_checks VALUES (NULL, 1, 'use', 'Slash::ResKey::Checks::ProxyScan', 1001); +#INSERT INTO reskey_resource_checks VALUES (NULL, 1, 'use', 'Slash::ResKey::Checks::ProxyScan', 1001); # dummy example of how to disable the Slash::ResKey::Checks::User check for "touch" # (maybe, for example, because the check isn't needed) @@ -66,8 +66,8 @@ INSERT INTO reskey_vars VALUES (1, 'user_seclev', 0, 'Minimum seclev to use resource'); INSERT INTO reskey_vars VALUES (1, 'duration_max-uses', 30, 'how many uses per timeframe'); INSERT INTO reskey_vars VALUES (1, 'duration_max-failures', 10, 'how many failures per reskey'); -INSERT INTO reskey_vars VALUES (1, 'duration_uses', 120, 'min duration (in seconds) between uses'); -INSERT INTO reskey_vars VALUES (1, 'duration_creation-use', 5, 'min duration between (in seconds) creation and use'); +INSERT INTO reskey_vars VALUES (1, 'duration_uses', 60, 'min duration (in seconds) between uses'); +INSERT INTO reskey_vars VALUES (1, 'duration_creation-use', 10, 'min duration between (in seconds) creation and use'); Modified: slashjp/branches/upstream/current/plugins/Submit/submit.pl =================================================================== --- slashjp/branches/upstream/current/plugins/Submit/submit.pl 2008-03-31 12:09:17 UTC (rev 559) +++ slashjp/branches/upstream/current/plugins/Submit/submit.pl 2008-04-01 03:35:14 UTC (rev 560) @@ -2,7 +2,7 @@ # This code is a part of Slash, and is released under the GPL. # Copyright 1997-2005 by Open Source Technology Group. See README # and COPYING for more information, or see http://slashcode.com/. -# $Id: submit.pl,v 1.144 2007/10/23 20:56:46 tvroom Exp $ +# $Id: submit.pl,v 1.145 2008/03/18 16:45:13 tvroom Exp $ use strict; use Slash 2.003; # require Slash 2.3.x @@ -265,6 +265,9 @@ } } + my $url = ""; + $url = $slashdb->getUrl($sub->{url_id}) if $sub->{url_id}; + foreach my $memory (@$sub_memory) { my $match = $memory->{submatch}; @@ -272,7 +275,8 @@ $sub->{name} =~ m/$match/i || $sub->{subj} =~ m/$match/i || $sub->{ipid} =~ m/$match/i || - $sub->{story} =~ m/$match/i) { + $sub->{story} =~ m/$match/i || + $url =~ m/$match/i ) { push @$subnotes_ref, $memory; } } Modified: slashjp/branches/upstream/current/plugins/TagModeration/TagModeration.pm =================================================================== --- slashjp/branches/upstream/current/plugins/TagModeration/TagModeration.pm 2008-03-31 12:09:17 UTC (rev 559) +++ slashjp/branches/upstream/current/plugins/TagModeration/TagModeration.pm 2008-04-01 03:35:14 UTC (rev 560) @@ -1,7 +1,7 @@ # This code is a part of Slash, and is released under the GPL. # Copyright 1997-2005 by Open Source Technology Group. See README # and COPYING for more information, or see http://slashcode.com/. -# $Id: TagModeration.pm,v 1.5 2008/02/21 01:01:52 pudge Exp $ +# $Id: TagModeration.pm,v 1.10 2008/03/19 08:25:31 pudge Exp $ package Slash::TagModeration; @@ -17,7 +17,7 @@ use base 'Slash::DB::Utility'; use base 'Slash::DB::MySQL'; -($VERSION) = ' $Revision: 1.5 $ ' =~ /\$Revision:\s+([^\s]+)/; +($VERSION) = ' $Revision: 1.10 $ ' =~ /\$Revision:\s+([^\s]+)/; sub new { my($class, $user) = @_; @@ -91,10 +91,12 @@ $self->countUsers({ max => 1 }), $self->getReasons ); - $html->{$score} = "(Score:$points"; + $html->{$score} = "Score:$points"; + $html->{$score} = qq[<a href="#" onclick="getModalPrefs('modcommentlog', 'Moderation Comment Log', $cid); return false">$html->{$score}</a>] + if $constants->{modal_prefs_active} && !$user->{is_anon}; $html->{$score} .= ", $reasons->{$comment->{reason}}{name}" if $comment->{reason} && $reasons->{$comment->{reason}}; - $html->{$score} .= ")"; + $html->{$score} = "($html->{$score})"; my $ptstr = $user->{points} == 1 ? 'point' : 'points'; $html->{$select} = "Moderated '$reasons->{$reason}{name}.' $user->{points} $ptstr left."; Modified: slashjp/branches/upstream/current/plugins/Tags/PLUGIN =================================================================== --- slashjp/branches/upstream/current/plugins/Tags/PLUGIN 2008-03-31 12:09:17 UTC (rev 559) +++ slashjp/branches/upstream/current/plugins/Tags/PLUGIN 2008-04-01 03:35:14 UTC (rev 560) @@ -1,4 +1,4 @@ -# $Id: PLUGIN,v 1.14 2007/12/06 02:49:31 jamiemccarthy Exp $ +# $Id: PLUGIN,v 1.15 2008/03/19 14:49:35 jamiemccarthy Exp $ name=Tags description="Tags" htdoc=tags.pl @@ -6,6 +6,7 @@ mysql_schema=mysql_schema.sql requiresplugin=Ajax task=tagbox.pl +task=tags_tagnamecache.pl task=tags_udc.pl task=tags_updateclouts.pl template=templates/data;tags;default Modified: slashjp/branches/upstream/current/plugins/Tags/Tags.pm =================================================================== --- slashjp/branches/upstream/current/plugins/Tags/Tags.pm 2008-03-31 12:09:17 UTC (rev 559) +++ slashjp/branches/upstream/current/plugins/Tags/Tags.pm 2008-04-01 03:35:14 UTC (rev 560) @@ -1,7 +1,7 @@ # This code is a part of Slash, and is released under the GPL. # Copyright 1997-2005 by Open Source Technology Group. See README # and COPYING for more information, or see http://slashcode.com/. -# $Id: Tags.pm,v 1.101 2008/02/28 19:51:01 jamiemccarthy Exp $ +# $Id: Tags.pm,v 1.107 2008/03/19 14:49:35 jamiemccarthy Exp $ package Slash::Tags; @@ -17,7 +17,7 @@ use base 'Slash::DB::Utility'; use base 'Slash::DB::MySQL'; -($VERSION) = ' $Revision: 1.101 $ ' =~ /\$Revision:\s+([^\s]+)/; +($VERSION) = ' $Revision: 1.107 $ ' =~ /\$Revision:\s+([^\s]+)/; # FRY: And where would a giant nerd be? THE LIBRARY! @@ -603,6 +603,9 @@ } # Is it descriptive? + # XXX this should be optimized by retrieving the list of _all_ + # descriptive tagnames in memcached or the local closure and + # doing a lookup on that. if ($types->{describe} && !$clid) { $tn_data = $self->getTagnameDataFromId($tagnameid); $clid = $types->{describe} if $tn_data->{descriptive}; @@ -685,7 +688,8 @@ for my $uid (keys %uid) { # XXX getUser($foo, 'clout') does not work at the moment, # so getUser($foo)->{clout} is used instead - $user_clout_hr->{$uid} = $self->getUser($uid)->{clout}; + my $user = $self->getUser($uid); + $user_clout_hr->{$uid} = $self->getUser($uid)->{clout} if $user; } @@ -704,7 +708,9 @@ $tagname_clid = $default_clout_clid; } my $tagname_clout_name = $clout_types->{ $tagname_clid }; - $tag_hr->{user_clout} = $mult * $user_clout_hr ->{$tag_hr->{uid}}{$tagname_clout_name}; + my $clout = $user_clout_hr->{$tag_hr->{uid}}; + my $clout_specific = $clout ? $clout->{$tagname_clout_name} : 0; + $tag_hr->{user_clout} = $mult * $clout_specific; $tag_hr->{total_clout} = $tag_hr->{tag_clout} * $tag_hr->{tagname_clout} * $tag_hr->{user_clout}; } } @@ -849,7 +855,7 @@ # my $value = $mcd->get("$mcdkey$name"); # return $value if defined $value; # } - my $private_clause = $options->{include_private} ? '' : " AND private='no'"; + my $private_clause = ref($options) && $options->{include_private} ? '' : " AND private='no'"; my $id = $self->getTagnameidFromNameIfExists($name); return [ ] if !$id; my $hr_ar = $self->sqlSelectAllHashrefArray( @@ -965,7 +971,7 @@ my($self, $constants, $user, $form) = @_; my $sidenc = $form->{sidenc}; - my $sid = $sidenc; $sid =~ tr{:}{/}; + my $sid = $sidenc; $sid =~ tr{-}{/}; my $stoid = $self->getStoidFromSid($sid); my $tags_reader = getObject('Slash::Tags', { db_type => 'reader' }); #print STDERR scalar(localtime) . " ajaxGetUserStory for stoid=$stoid sidenc=$sidenc tr=$tags_reader\n"; @@ -1023,7 +1029,7 @@ sub ajaxGetAdminStory { my($slashdb, $constants, $user, $form) = @_; my $sidenc = $form->{sidenc}; - my $sid = $sidenc; $sid =~ tr{:}{/}; + my $sid = $sidenc; $sid =~ tr{-}{/}; if (!$sid || $sid !~ regexSid() || !$user->{is_admin}) { return getData('error', {}, 'tags'); @@ -1155,7 +1161,7 @@ sub ajaxCreateForStory { my($slashdb, $constants, $user, $form) = @_; my $sidenc = $form->{sidenc}; - my $sid = $sidenc; $sid =~ tr{:}{/}; + my $sid = $sidenc; $sid =~ tr{-}{/}; my $tags = getObject('Slash::Tags'); my $tagsstring = $form->{tags}; if (!$sid || $sid !~ regexSid() || $user->{is_anon} || !$tags) { @@ -1189,6 +1195,30 @@ return $retval; } +sub ajaxDeactivateTag { + my($self, $constants, $user, $form) = @_; + my $type = $form->{type} || "stories"; + my $tags = getObject('Slash::Tags'); # XXX isn't this the same as $self? -Jamie + + my ($table, $id); + + if ($type eq "firehose") { + my $firehose = getObject("Slash::FireHose"); + my $item = $firehose->getFireHose($form->{id}); + ($table, $id) = $tags->getGlobjTarget($item->{globjid}); + } else { + # XXX doesn't work yet for stories or urls + return; + } + + $tags->deactivateTag({ + uid => $user->{uid}, + name => $form->{tag}, + table => $table, + id => $id, + }); +} + sub ajaxProcessAdminTags { my($slashdb, $constants, $user, $form) = @_; #print STDERR "ajaxProcessAdminTags\n"; @@ -1197,7 +1227,7 @@ my($id, $table, $sid, $sidenc, $itemid); if ($type eq "stories") { $sidenc = $form->{sidenc}; - $sid = $sidenc; $sid =~ tr{:}{/}; + $sid = $sidenc; $sid =~ tr{-}{/}; $id = $slashdb->getStoidFromSid($sid); $table = "stories"; } elsif ($type eq "urls") { @@ -1293,7 +1323,7 @@ my $table; if ($form->{type} eq "stories") { my $sidenc = $form->{sidenc}; - my $sid = $sidenc; $sid =~ tr{:}{/}; + my $sid = $sidenc; $sid =~ tr{-}{/}; $id = $slashdb->getStoidFromSid($sid); $table = "stories" } elsif ($form->{type} eq "urls") { @@ -1380,6 +1410,13 @@ my $len = length($prefix); my $notize = $form->{prefix} =~ /^([-!])/ ? $1 : ''; + my $minlen = $constants->{tags_prefixlist_minlen} || 3; + if ($len < $minlen) { + # Too short to give a meaningful suggestion, and the + # shorter the prefix the longer the DB query takes. + return ''; + } + my $tnhr = $tags_reader->listTagnamesByPrefix($prefix); my @priority = @@ -1683,10 +1720,10 @@ sub listTagnamesActive { my($self, $options) = @_; my $constants = getCurrentStatic(); - my $max_num = $options->{max_num} || 100; - my $seconds = $options->{seconds} || (3600*6); - my $include_private = $options->{include_private} || 0; - my $min_slice = $options->{min_slice} || 0; + my $max_num = ref($options) && $options->{max_num} || 100; + my $seconds = ref($options) && $options->{seconds} || (3600*6); + my $include_private = ref($options) && $options->{include_private} || 0; + my $min_slice = ref($options) && $options->{min_slice} || 0; $min_slice = 0 if !$constants->{plugin}{FireHose}; # This seems like a horrendous query, but I _think_ it will run @@ -1791,8 +1828,8 @@ sub listTagnamesRecent { my($self, $options) = @_; my $constants = getCurrentStatic(); - my $seconds = $options->{seconds} || (3600*6); - my $include_private = $options->{include_private} || 0; + my $seconds = ref($options) && $options->{seconds} || (3600*6); + my $include_private = ref($options) && $options->{include_private} || 0; my $private_clause = $include_private ? '' : " AND private='no'"; my $recent_ar = $self->sqlSelectColArrayref( 'DISTINCT tagnames.tagname', @@ -1820,24 +1857,65 @@ $a2 cmp $b2 || $a1 cmp $b1; } +{ # closure +my $tagname_cache_lastcheck = 1; sub listTagnamesByPrefix { my($self, $prefix_str, $options) = @_; my $constants = getCurrentStatic(); my $reader = getObject('Slash::DB', { db_type => 'reader' }); - my $like_str = $self->sqlQuote("$prefix_str%"); - my $minc = $self->sqlQuote($options->{minc} || $constants->{tags_prefixlist_minc} || 4); - my $mins = $self->sqlQuote($options->{mins} || $constants->{tags_prefixlist_mins} || 3); - my $num = $options->{num} || $constants->{tags_prefixlist_num}; - $num = 10 if !$num || $num !~ /^(\d+)$/ || $num < 1; + my $ret_hr; my $mcd = undef; $mcd = $self->getMCD() unless $options; my $mcdkey = "$self->{_mcd_keyprefix}:tag_prefx:"; if ($mcd) { - my $ret_str = $mcd->get("$mcdkey$prefix_str"); - return $ret_str if $ret_str; + $ret_hr = $mcd->get("$mcdkey$prefix_str"); + return $ret_hr if $ret_hr; } + # If the tagname_cache table has been filled, use it. + # Otherwise, perform an expensive query directly. + # The logic is that $tagname_cache_lastcheck stays a + # large positive number (a timestamp) until we determine + # that the table _does_ have rows, at which point that + # number drops to 0. Once its value hits 0, it is never + # checked again. + if ($tagname_cache_lastcheck > 0 && $tagname_cache_lastcheck < time()-3600) { + my $rows = $reader->sqlCount('tagname_cache'); + $tagname_cache_lastcheck = $rows ? 0 : time; + } + my $use_cache_table = $tagname_cache_lastcheck ? 0 : 1; + if ($use_cache_table) { + $ret_hr = $self->listTagnamesByPrefix_cache($prefix_str, $options); + } else { + $ret_hr = $self->listTagnamesByPrefix_direct($prefix_str, $options); + } + + if ($mcd) { + # The expiration we use is much longer than the tags_cache_expire + # var since the cache data changes only once a day. + $mcd->set("$mcdkey$prefix_str", $ret_hr, 3600); + } + + return $ret_hr; +} +} + +# This is a quick-and-dirty (and not very accurate) estimate which +# is only performed for a site which has not built its tagname_cache +# table yet. Hopefully most sites will use this the first day the +# Tags plugin is installed and then never again. + +sub listTagnamesByPrefix_direct { + my($self, $prefix_str, $options) = @_; + my $constants = getCurrentStatic(); + my $like_str = $self->sqlQuote("$prefix_str%"); + my $minc = $self->sqlQuote($options->{minc} || $constants->{tags_prefixlist_minc} || 4); + my $mins = $self->sqlQuote($options->{mins} || $constants->{tags_prefixlist_mins} || 3); + my $num = $options->{num} || $constants->{tags_prefixlist_num}; + $num = 10 if !$num || $num !~ /^(\d+)$/ || $num < 1; + + my $reader = getObject('Slash::DB', { db_type => 'reader' }); my $ar = $reader->sqlSelectAllHashrefArray( 'tagname, COUNT(DISTINCT tags.uid) AS c, @@ -1856,13 +1934,25 @@ for my $hr (@$ar) { $ret_hr->{ $hr->{tagname} } = $hr->{sc}; } - if ($mcd) { - my $mcdexp = $constants->{tags_cache_expire} || 180; - $mcd->set("$mcdkey$prefix_str", $ret_hr, $mcdexp) - } return $ret_hr; } +sub listTagnamesByPrefix_cache { + my($self, $prefix_str, $options) = @_; + my $constants = getCurrentStatic(); + my $like_str = $self->sqlQuote("$prefix_str%"); + my $num = $options->{num} || $constants->{tags_prefixlist_num}; + $num = 10 if !$num || $num !~ /^(\d+)$/ || $num < 1; + + my $reader = getObject('Slash::DB', { db_type => 'reader' }); + my $ret_hr = $reader->sqlSelectAllKeyValue( + 'tagname, weight', + 'tagname_cache', + "tagname LIKE $like_str", + "ORDER BY weight DESC LIMIT $num"); + return $ret_hr; +} + sub getPrivateTagnames { my ($self) = @_; my $user = getCurrentUser; Modified: slashjp/branches/upstream/current/plugins/Tags/mysql_dump.sql =================================================================== --- slashjp/branches/upstream/current/plugins/Tags/mysql_dump.sql 2008-03-31 12:09:17 UTC (rev 559) +++ slashjp/branches/upstream/current/plugins/Tags/mysql_dump.sql 2008-04-01 03:35:14 UTC (rev 560) @@ -1,5 +1,5 @@ # -# $Id: mysql_dump.sql,v 1.34 2008/02/28 19:51:01 jamiemccarthy Exp $ +# $Id: mysql_dump.sql,v 1.36 2008/03/11 19:57:26 jamiemccarthy Exp $ # INSERT INTO vars (name, value, description) VALUES ('memcached_exptime_tags', '3600', 'Seconds to cache tag data in memcached'); @@ -10,6 +10,7 @@ INSERT INTO vars (name, value, description) VALUES ('tags_cache_expire', '180', 'Local data cache expiration for tags'); INSERT INTO vars (name, value, description) VALUES ('tags_list_mintc', '4', 'Minimum value of total_clout for tagged items shown at /tags/foo'); INSERT INTO vars (name, value, description) VALUES ('tags_prefixlist_minc', '4', 'Minimum value of c (count) for tagnames returned by listTagnamesByPrefix'); +INSERT INTO vars (name, value, description) VALUES ('tags_prefixlist_minlen', '3', 'Minimum length of a tag prefix to bother looking up suggestions for'); INSERT INTO vars (name, value, description) VALUES ('tags_prefixlist_mins', '3', 'Minimum value of s (clout sum) for tagnames returned by listTagnamesByPrefix'); INSERT INTO vars (name, value, description) VALUES ('tags_prefixlist_num', '10', 'Number of tagnames returned by listTagnamesByPrefix'); INSERT INTO vars (name, value, description) VALUES ('tags_prefixlist_priority', 'back bookmark feed hold journal none quik submission story', 'Tagnames to give priority to on autocomplete'); @@ -48,6 +49,7 @@ INSERT INTO ajax_ops VALUES (NULL, 'tags_admin_commands', 'Slash::Tags', 'ajaxProcessAdminTags', 'ajax_admin', 'use'); INSERT INTO ajax_ops VALUES (NULL, 'tags_history', 'Slash::Tags', 'ajaxTagHistory', 'ajax_admin', 'createuse'); INSERT INTO ajax_ops VALUES (NULL, 'tags_list_tagnames', 'Slash::Tags', 'ajaxListTagnames', 'ajax_tags_read', 'createuse'); +INSERT INTO ajax_ops VALUES (NULL, 'tags_deactivate', 'Slash::Tags', 'ajaxDeactivateTag', 'ajax_tags_write', 'use'); INSERT INTO menus VALUES (NULL, 'tagszg', 'Active', 'active', '[% gSkin.rootdir %]/tags', 1, 1, 1); INSERT INTO menus VALUES (NULL, 'tagszg', 'Recent', 'recent', '[% gSkin.rootdir %]/tags/recent', 1, 1, 2); Modified: slashjp/branches/upstream/current/plugins/Tags/mysql_schema.sql =================================================================== --- slashjp/branches/upstream/current/plugins/Tags/mysql_schema.sql 2008-03-31 12:09:17 UTC (rev 559) +++ slashjp/branches/upstream/current/plugins/Tags/mysql_schema.sql 2008-04-01 03:35:14 UTC (rev 560) @@ -1,5 +1,5 @@ # -# $Id: mysql_schema.sql,v 1.17 2007/09/26 21:25:51 jamiemccarthy Exp $ +# $Id: mysql_schema.sql,v 1.18 2008/03/19 14:49:36 jamiemccarthy Exp $ # DROP TABLE IF EXISTS tags; @@ -33,7 +33,19 @@ PRIMARY KEY tagnameid (tagnameid), UNIQUE tagname (tagname) ) TYPE=InnoDB; - + +# tagname_cache is not normalized because it's intended to be used +# for quick lookups. + +DROP TABLE IF EXISTS tagname_cache; +CREATE TABLE tagname_cache ( + tagnameid int UNSIGNED NOT NULL, + tagname VARCHAR(64) NOT NULL, + weight FLOAT UNSIGNED DEFAULT 0.0 NOT NULL, + PRIMARY KEY tagnameid (tagnameid), + UNIQUE tagname (tagname), +) TYPE=InnoDB; + DROP TABLE IF EXISTS tagname_params; CREATE TABLE tagname_params ( tagnameid int UNSIGNED NOT NULL, Modified: slashjp/branches/upstream/current/plugins/Tags/tagbox.pl =================================================================== --- slashjp/branches/upstream/current/plugins/Tags/tagbox.pl 2008-03-31 12:09:17 UTC (rev 559) +++ slashjp/branches/upstream/current/plugins/Tags/tagbox.pl 2008-04-01 03:35:14 UTC (rev 560) @@ -2,7 +2,7 @@ # This code is a part of Slash, and is released under the GPL. # Copyright 1997-2005 by Open Source Technology Group. See README # and COPYING for more information, or see http://slashcode.com/. -# $Id: tagbox.pl,v 1.18 2008/01/30 22:42:38 jamiemccarthy Exp $ +# $Id: tagbox.pl,v 1.19 2008/03/10 20:39:02 jamiemccarthy Exp $ use strict; @@ -282,7 +282,7 @@ sub insert_feederlog { my($tagbox, $feeder_ar) = @_; for my $feeder_hr (@$feeder_ar) { -main::tagboxLog("addFeederInfo: tbid=$tagbox->{tbid} tagid=$feeder_hr->{tagid} affected_id=$feeder_hr->{affected_id} imp=$feeder_hr->{importance}"); +{ my $fstr = Dumper($feeder_hr); $fstr =~ s/\s+/ /g; main::tagboxLog("addFeederInfo: tbid=$tagbox->{tbid} f: $fstr"); } $tagboxdb->addFeederInfo($tagbox->{tbid}, $feeder_hr); } } @@ -300,6 +300,10 @@ for my $affected_hr (@$affected_ar) { my $tagbox = $tagboxdb->getTagboxes($affected_hr->{tbid}, [qw( object )]); #my $ad = Dumper($affected_hr); $ad =~ s/\s+/ /g; my $tb = Dumper($tagbox); $tb =~ s/\s+/ /g; print STDERR "r_t_u affected_hr: $ad tagbox: $tb\n"; +if ($affected_hr->{tbid} == 17) { +my $feeder_ar = $tagboxdb->sqlSelectAllHashrefArray('*', 'tagboxlog_feeder', "tbid=17 AND affected_id=$affected_hr->{affected_id}", 'ORDER BY tfid'); +print STDERR "r_t_u rows for tbid=17 id=$affected_hr->{affected_id}: " . Dumper($feeder_ar) +} $tagbox->{object}->run($affected_hr->{affected_id}); $tagboxdb->markTagboxRunComplete($affected_hr); last if time() >= $run_until || $task_exit_flag; Added: slashjp/branches/upstream/current/plugins/Tags/tags_tagnamecache.pl =================================================================== --- slashjp/branches/upstream/current/plugins/Tags/tags_tagnamecache.pl (rev 0) +++ slashjp/branches/upstream/current/plugins/Tags/tags_tagnamecache.pl 2008-04-01 03:35:14 UTC (rev 560) @@ -0,0 +1,144 @@ +#!/usr/bin/perl -w +# This code is a part of Slash, and is released under the GPL. +# Copyright 1997-2005 by Open Source Technology Group. See README +# and COPYING for more information, or see http://slashcode.com/. +# $Id: tags_tagnamecache.pl,v 1.1 2008/03/21 04:10:35 jamiemccarthy Exp $ + +# Once a day, rewrite the tags_tagnamecache table, used for finding +# tagname suggestions based on prefixes. + +use strict; +use vars qw( %task $me $task_exit_flag ); +use Slash::DB; +use Slash::Display; +use Slash::Utility; +use Slash::Constants ':slashd'; + +(my $VERSION) = ' $Revision: 1.1 $ ' =~ /\$Revision:\s+([^\s]+)/; + +$task{$me}{timespec} = "30 6 * * *"; +$task{$me}{timespec_panic_1} = ''; # not that important +$task{$me}{fork} = SLASHD_NOWAIT; + +$task{$me}{code} = sub { + my($virtual_user, $constants, $slashdb, $user) = @_; + my $tagsdb = getObject('Slash::Tags'); + my $tagsdb_reader = getObject('Slash::Tags', { db_type => 'reader' }); + my $daysback = $constants->{tags_tagnamecache_daysback} || 180; + my $min_tagid = getMinimumTagid($tagsdb, $daysback); + my $ar = getTagnameList($tagsdb_reader, $min_tagid); + my $rows_replaced = replaceTagnames($tagsdb, $ar); + my $rows_deleted = deleteTagnamesNotIn($tagsdb, $ar); + my $total_rows = $tagsdb->sqlCount('tagname_cache'); + return "replaced $rows_replaced, deleted $rows_deleted, total $total_rows"; +}; + +sub getMinimumTagid { + my($tagsdb, $daysback) = @_; + my $min = $tagsdb->sqlSelectNumericKeyAssumingMonotonic( + 'tags', 'min', 'tagid', + "created_at >= DATE_SUB(NOW(), INTERVAL $daysback DAY)"); + return $min; +} + +# For now, let's include private tagnames in this list. It's not +# revealing private information since it's completely aggregated, +# and while suggesting tagnames like 'nod' and 'nix' may not be +# helpful, suggesting 'troll' and 'interesting' seems OK. + +sub getTagnameList { + my($tagsdb_reader, $min_tagid) = @_; + $min_tagid ||= 1; + + my $constants = getCurrentStatic(); + my $minc = $tagsdb_reader->sqlQuote($constants->{tags_prefixlist_minc} || 4); + my $mins = $tagsdb_reader->sqlQuote($constants->{tags_prefixlist_mins} || 3); + # $maxnum is to prevent $tagnameid_str from exceeding MySQL limits. + # Default max_allowed_packet should be 16 MB, so an ~80K query + # should be perfectly fine. + my $maxnum = 10000; + + # Get the list of tagnameids sorted in a very rough order of + # "importance." + # Note that the query uses multiple columns to sort the data, + # but we skim off only the tagnameid on the client side since + # that's all we care about. + + my $tagnameid_ar = $tagsdb_reader->sqlSelectColArrayref( + 'tags.tagnameid, + COUNT(DISTINCT tags.uid) AS c, + SUM(tag_clout * IF(value IS NULL, 1, value)) AS s, + COUNT(DISTINCT tags.uid)/3 + SUM(tag_clout * IF(value IS NULL, 1, value)) AS sc', + 'tags, users_info, tagnames + LEFT JOIN tagname_params USING (tagnameid)', + "tagnames.tagnameid=tags.tagnameid + AND tags.uid=users_info.uid + AND tags.inactivated IS NULL + AND tagid >= $min_tagid", + "GROUP BY tags.tagnameid + HAVING c >= $minc AND s >= $mins + ORDER BY sc DESC, tagname ASC + LIMIT $maxnum"); + return [ ] if !$tagnameid_ar || !@$tagnameid_ar; + my $tagnameid_str = join(',', sort { $a <=> $b } @$tagnameid_ar); + + # Now get the total list of tags (which will be very large, + # so this is a slow query) + + my $tag_ar = $tagsdb_reader->sqlSelectAllHashrefArray( + '*, UNIX_TIMESTAMP(created_at) AS created_at_ut', + 'tags', + "tagnameid IN ($tagnameid_str) + AND tagid >= $min_tagid + AND tags.inactivated IS NULL"); + + # This will call getUser() for every uid in the above list and + # getTagnameidClid() for every tagnameid (up to 10,000). So + # this will be a very slow operation. + + $tagsdb_reader->addCloutsToTagArrayref($tag_ar); + + my $tagnameid_sum = { }; + for my $hr (@$tag_ar) { + $tagnameid_sum->{ $hr->{tagnameid} } ||= 0; + $tagnameid_sum->{ $hr->{tagnameid} } += $hr->{total_clout}; + } + my $ret_ar = [ ]; + for my $tagnameid (@$tagnameid_ar) { + my $sum = $tagnameid_sum->{$tagnameid}; + next unless $sum > 0; + my $tagname = $tagsdb_reader->getTagnameDataFromId($tagnameid)->{tagname}; + push @$ret_ar, { + tagnameid => $tagnameid, + tagname => $tagname, + weight => $sum, + }; + } + + return $ret_ar; +} + +sub replaceTagnames { + my($tagsdb, $ar) = @_; + my $rows = 0; + for my $hr (@$ar) { + $rows += $tagsdb->sqlReplace('tagname_cache', $hr); + Time::HiRes::sleep(0.01); + } + return $rows; +} + +sub deleteTagnamesNotIn { + my($tagsdb, $ar) = @_; + my $tagnameid_str = join(',', + sort { $a <=> $b } + map { $_->{tagnameid} } + @$ar + ); + my $rows = $tagsdb->sqlDelete('tagname_cache', + "tagnameid NOT IN ($tagnameid_str)"); + return $rows; +} + +1; + Modified: slashjp/branches/upstream/current/plugins/Tags/templates/tagsstorydivtagbox;misc;default =================================================================== --- slashjp/branches/upstream/current/plugins/Tags/templates/tagsstorydivtagbox;misc;default 2008-03-31 12:09:17 UTC (rev 559) +++ slashjp/branches/upstream/current/plugins/Tags/templates/tagsstorydivtagbox;misc;default 2008-04-01 03:35:14 UTC (rev 560) @@ -13,7 +13,7 @@ __name__ tagsstorydivtagbox __template__ -[% sidenc = story.sid.replace("/",":") %] +[% sidenc = story.sid.replace("/","-") # no '/'s in html ids (see: http://www.w3.org/TR/html401/types.html) %] [% IF user.tags_canread_stories %] <div id="tagbox-[% sidenc %]" class="tags"> @@ -54,4 +54,4 @@ __seclev__ 10000 __version__ -$Id: tagsstorydivtagbox;misc;default,v 1.10 2007/10/24 00:30:08 scc Exp $ +$Id: tagsstorydivtagbox;misc;default,v 1.11 2008/03/13 17:15:30 scc Exp $ Modified: slashjp/branches/upstream/current/sql/mysql/defaults.sql =================================================================== --- slashjp/branches/upstream/current/sql/mysql/defaults.sql 2008-03-31 12:09:17 UTC (rev 559) +++ slashjp/branches/upstream/current/sql/mysql/defaults.sql 2008-04-01 03:35:14 UTC (rev 560) @@ -3,7 +3,7 @@ #-------------------------------------------------------- # Server version 3.23.26-beta-log # -# $Id: defaults.sql,v 1.393 2008/02/28 20:44:48 pudge Exp $ +# $Id: defaults.sql,v 1.394 2008/03/12 16:48:57 pudge Exp $ # # @@ -832,7 +832,7 @@ INSERT INTO vars (name, value, description) VALUES ('cur_performance_stats_lastid', '0', 'accesslogid to start searching at'); INSERT INTO vars (name, value, description) VALUES ('cur_performance_stats_weeks', '8', 'number of weeks back to compare current stats to'); INSERT INTO vars (name, value, description) VALUES ('currentqid',1,'The Current Question on the homepage pollbooth'); -INSERT INTO vars (name, value, description) VALUES ('cvs_tag_currentcode','T_2_5_0_196','The current cvs tag that the code was updated to - this does not affect site behavior but may be useful for your records'); +INSERT INTO vars (name, value, description) VALUES ('cvs_tag_currentcode','T_2_5_0_197','The current cvs tag that the code was updated to - this does not affect site behavior but may be useful for your records'); INSERT INTO vars (name, value, description) VALUES ('datadir','/usr/local/slash/www.example.com','What is the root of the install for Slash'); INSERT INTO vars (name, value, description) VALUES ('db_auto_increment_increment','1','If your master DB uses auto_increment_increment, i.e. multiple master replication, echo its value into this var'); INSERT INTO vars (name, value, description) VALUES ('dbsparklines_disp','0','Display dbsparklines in the currentAdminUsers box?'); Modified: slashjp/branches/upstream/current/sql/mysql/upgrades =================================================================== --- slashjp/branches/upstream/current/sql/mysql/upgrades 2008-03-31 12:09:17 UTC (rev 559) +++ slashjp/branches/upstream/current/sql/mysql/upgrades 2008-04-01 03:35:14 UTC (rev 560) @@ -10,7 +10,7 @@ # after X started at the same time that X was tagged. # -# $Id: upgrades,v 1.1318 2008/02/28 20:44:48 pudge Exp $ +# $Id: upgrades,v 1.1328 2008/03/21 02:44:47 pudge Exp $ # # BEGIN tf23's additions @@ -5049,8 +5049,6 @@ # not for slashdot UPDATE vars SET value = 'yes no binspam dupe notthebest offtopic stupid slownewsday interesting funny insightful' WHERE name = 'tagbox_top_excludetagnames'; -# PUDGE LAST UPDATED HERE - # 2007-12-05 UPDATE vars SET value = 'T_2_5_0_185' WHERE name = 'cvs_tag_currentcode'; @@ -5136,8 +5134,6 @@ # 2008-02-13 UPDATE vars SET value = 'T_2_5_0_194' WHERE name = 'cvs_tag_currentcode'; -# SLASHDOT LAST UPDATED HERE - # For sites *without* plugins/Tags DELETE FROM clout_types; @@ -5147,8 +5143,6 @@ # 2008-02-20 UPDATE vars SET value = 'T_2_5_0_195' WHERE name = 'cvs_tag_currentcode'; -# SLASHCODE/USEPERL LAST UPDATED HERE - # for plugins/Tags INSERT INTO vars (name, value, description) VALUES ('tags_unknowntype_default_clid', '1', 'For tags of unknown type, which clout id do we pretend they are?'); INSERT INTO vars (name, value, description) VALUES ('tags_unknowntype_default_mult', '0.3', 'For tags of unknown type, what multiplier do we give to the tagging user clout or type tags_unknowntype_default_clid?'); @@ -5156,3 +5150,50 @@ # 2008-02-28 UPDATE vars SET value = 'T_2_5_0_196' WHERE name = 'cvs_tag_currentcode'; +# for plugins/Tags +INSERT INTO ajax_ops VALUES (NULL, 'tags_deactivate', 'Slash::Tags', 'ajaxDeactivateTag', 'ajax_tags_write', 'use'); +INSERT INTO vars (name, value, description) VALUES ('tags_prefixlist_minlen', '3', 'Minimum length of a tag prefix to bother looking up suggestions for'); + +# 2008-03-12 +UPDATE vars SET value = 'T_2_5_0_197' WHERE name = 'cvs_tag_currentcode'; + +# SLASHDOT LAST UPDATED HERE + +# for plugins/Ajax +UPDATE ajax_ops set reskey_name = 'ajax_user_static', reskey_type='createuse' WHERE op='admin_signoff'; + +# comments +DELETE FROM reskey_resource_checks WHERE rkrid = 1; +INSERT INTO reskey_resource_checks VALUES (NULL, 1, 'all', 'Slash::ResKey::Checks::User', 101); +INSERT INTO reskey_resource_checks VALUES (NULL, 1, 'all', 'Slash::ResKey::Checks::ACL', 201); +INSERT INTO reskey_resource_checks VALUES (NULL, 1, 'all', 'Slash::ResKey::Checks::AL2::AnonNoPost', 301); +INSERT INTO reskey_resource_checks VALUES (NULL, 1, 'all', 'Slash::ResKey::Checks::AL2::NoPostAnon', 401); +INSERT INTO reskey_resource_checks VALUES (NULL, 1, 'all', 'Slash::ResKey::Checks::AL2::NoPost', 501); +INSERT INTO reskey_resource_checks VALUES (NULL, 1, 'all', 'Slash::ResKey::Checks::AL2::Spammer', 531); +INSERT INTO reskey_resource_checks VALUES (NULL, 1, 'all', 'Slash::ResKey::Checks::Duration', 601); + +DELETE FROM reskey_vars WHERE rkrid = 1; +INSERT INTO reskey_vars VALUES (1, 'adminbypass', 1, 'If admin, bypass checks for duration, proxy, and user'); +INSERT INTO reskey_vars VALUES (1, 'acl_no', 'reskey_no_comments', 'If this ACL present, can\'t use resource'); +INSERT INTO reskey_vars VALUES (1, 'user_seclev', 0, 'Minimum seclev to use resource'); +INSERT INTO reskey_vars VALUES (1, 'duration_max-uses', 30, 'how many uses per timeframe'); +INSERT INTO reskey_vars VALUES (1, 'duration_max-failures', 10, 'how many failures per reskey'); +INSERT INTO reskey_vars VALUES (1, 'duration_uses', 60, 'min duration (in seconds) between uses'); +INSERT INTO reskey_vars VALUES (1, 'duration_creation-use', 10, 'min duration between (in seconds) creation and use'); + +# for plugins/Tags +CREATE TABLE tagname_cache ( + tagnameid int UNSIGNED NOT NULL, + tagname VARCHAR(64) NOT NULL, + weight FLOAT UNSIGNED DEFAULT 0.0 NOT NULL, + PRIMARY KEY tagnameid (tagnameid), + UNIQUE tagname (tagname) +) TYPE=InnoDB; + + +# 2008-03-19 +UPDATE vars SET value = 'T_2_5_0_198' WHERE name = 'cvs_tag_currentcode'; + +# SLASHCODE/USEPERL LAST UPDATED HERE + +# PUDGE LAST UPDATED HERE Modified: slashjp/branches/upstream/current/tagboxes/Despam/Despam.pm =================================================================== --- slashjp/branches/upstream/current/tagboxes/Despam/Despam.pm 2008-03-31 12:09:17 UTC (rev 559) +++ slashjp/branches/upstream/current/tagboxes/Despam/Despam.pm 2008-04-01 03:35:14 UTC (rev 560) @@ -2,7 +2,7 @@ # This code is a part of Slash, and is released under the GPL. # Copyright 1997-2005 by Open Source Technology Group. See README # and COPYING for more information, or see http://slashcode.com/. -# $Id: Despam.pm,v 1.7 2008/01/24 18:27:41 jamiemccarthy Exp $ +# $Id: Despam.pm,v 1.9 2008/03/12 14:27:28 jamiemccarthy Exp $ package Slash::Tagbox::Despam; @@ -28,7 +28,7 @@ use Data::Dumper; use vars qw( $VERSION ); -$VERSION = ' $Revision: 1.7 $ ' =~ /\$Revision:\s+([^\s]+)/; +$VERSION = ' $Revision: 1.9 $ ' =~ /\$Revision:\s+([^\s]+)/; use base 'Slash::DB::Utility'; # first for object init stuff, but really # needs to be second! figure it out. -- pudge @@ -53,9 +53,10 @@ my $constants = getCurrentStatic(); my $tagsdb = getObject('Slash::Tags'); - $self->{spamid} = $tagsdb->getTagnameidCreate('binspam'); - $self->{upvoteid} = $tagsdb->getTagnameidCreate($constants->{tags_upvote_tagname} || 'nod'); + $self->{spamid} = $tagsdb->getTagnameidCreate('binspam'); return undef unless $self->{spamid}; + $self->{upvoteid} = $tagsdb->getTagnameidCreate($constants->{tags_upvote_tagname} || 'nod'); + $self->{recalc_tbids} = undef; return $self; } @@ -91,6 +92,7 @@ }; push @$ret_ar, $ret_hr; } + main::tagboxLog("Despam->feed_newtags A " . scalar(@$ret_ar) . ": '@$ret_ar'"); return [ ] if !@$ret_ar; # Tags applied to globjs that have a firehose entry associated @@ -101,6 +103,7 @@ 'globjid', 'firehose', "globjid IN ($globjs_str)"); + main::tagboxLog("Despam->feed_newtags B " . scalar(@$fh_globjs_ar) . ": '@$fh_globjs_ar'"); return [ ] if !@$fh_globjs_ar; # if no affected globjs have firehose entries, short-circuit out my %fh_globjs = ( map { $_, 1 } @$fh_globjs_ar ); $ret_ar = [ grep { $fh_globjs{ $_->{affected_id} } } @$ret_ar ]; @@ -111,13 +114,10 @@ sub feed_deactivatedtags { my($self, $tags_ar) = @_; - # XXX This need not do anything, I don't think -- not even call - # feed_newtags. - # The way Despam is set up, 2 admin binspam tags will mark a globjid, - # and even if 1 of them is deactivated a moment later, we have no way - # to undo the process. - main::tagboxLog("Despam->feed_deactivatedtags called: tags_ar='" . join(' ', map { $_->{tagid} } @$tags_ar) . "', returning nothing"); - return [ ]; + main::tagboxLog("Despam->feed_deactivatedtags called: tags_ar='" . join(' ', map { $_->{tagid} } @$tags_ar) . "', calling feed_newtags"); + my $ret_ar = $self->feed_newtags($tags_ar); + main::tagboxLog("Despam->feed_deactivatedtags returning " . scalar(@$ret_ar)); + return $ret_ar; } sub feed_userchanges { @@ -134,6 +134,7 @@ my $firehose_db = getObject('Slash::FireHose'); my $slashdb = getCurrentDB(); + # Get the list of admin uids. my $admins = $tagsdb->getAdmins(); my $admin_in_str = join(',', sort { $a <=> $b } @@ -141,170 +142,281 @@ keys %$admins); return unless $admin_in_str; + # Get info about the firehose item that may have been tagged. my $affected_id_q = $self->sqlQuote($affected_id); - my $fhid = $self->sqlSelect('id', 'firehose', "globjid = $affected_id_q"); - warn "Slash::Tagbox::Despam->run bad data, fhid='$fhid' db='$firehose_db'" if !$fhid || !$firehose_db; + my $fhid = $self->sqlSelect('DISTINCT id', 'firehose', "globjid = $affected_id_q"); + if (!$fhid || !$firehose_db) { + main::tagboxLog("Slash::Tagbox::Despam->run bad data, fhid='$fhid' db='$firehose_db'"); + return ; + } my $fhitem = $firehose_db->getFireHose($fhid); + + # Get info about the uid and ipid that submitted the firehose item. + # We only track ipid for actual submissions, not journals/bookmarks. my $submitter_uid = $fhitem->{uid}; - my $submitter_srcid = $fhitem->{srcid_32}; + my $submitter_ipid = ''; + my $types = $slashdb->getGlobjTypes(); + my $submission_gtid = $types->{submissions}; + if ($submission_gtid) { + $submitter_ipid = $slashdb->sqlSelect( + 'ipid', + 'globjs, submissions', + "globjid=$affected_id + AND gtid=$submission_gtid + AND target_id=subid" + ) || ''; + } - my $binspam_count = $slashdb->sqlCount( - 'tags, firehose', - "tags.uid IN ($admin_in_str) - AND tags.inactivated IS NULL - AND tags.tagnameid = $self->{spamid} - AND tags.globjid = firehose.globjid - AND firehose.uid = $submitter_uid"); - my $binspam_tagids = $slashdb->sqlSelectColArrayref( - 'tagid', - 'tags, firehose', - "tags.uid IN ($admin_in_str) - AND tags.inactivated IS NULL - AND tags.tagnameid = $self->{spamid} - AND tags.globjid = firehose.globjid - AND firehose.uid = $submitter_uid"); - main::tagboxLog(sprintf("%s->run marking fhid %d (%d) as is_spam (for count %d on uid %d: '%s')", - ref($self), $fhid, $affected_id, $binspam_count, $submitter_uid, join(' ', @$binspam_tagids))); - $firehose_db->setFireHose($fhid, { is_spam => 'yes' }); + # First figure out how many times the globjid was tagged binspam by + # an admin. It may be zero (if forceFeederRecalc was called, or if + # an old binspam tag was deactivated). Even one admin binspam tag + # is enough to mark the individual item as binspam. + my $binspam_count_globjid = $slashdb->sqlCount( + 'tags', + "globjid=$affected_id + AND tagnameid=$self->{spamid} + AND uid IN ($admin_in_str) + AND inactivated IS NULL"); + my $is_spam = $binspam_count_globjid > 0 ? 1 : 0; - if (isAnon($submitter_uid)) { - # Non-logged-in user, check by IP (srcid_32) - if ($submitter_srcid && - $binspam_count > $constants->{tagbox_despam_binspamsallowed_ip} - ) { - main::tagboxLog(sprintf("%s->run marking srcid %s for %d admin binspam tags, based on %d (%d)", - ref($self), $submitter_srcid, $binspam_count, $fhid, $affected_id)); - $self->despam_srcid($submitter_srcid, $binspam_count); - } - } else { - # Logged-in user, check by uid - if ($binspam_count > $constants->{tagbox_despam_binspamsallowed}) { - main::tagboxLog(sprintf("%s->run marking uid %d for %d admin binspam tags, based on %d (%d)", - ref($self), $submitter_uid, $binspam_count, $fhid, $affected_id)); - $self->despam_uid($submitter_uid, $binspam_count); - } + # Now see how many times this globjid's uid (or, if anonymous, ipid) + # was tagged binspam by an admin. If greater than a certain + # threshold, that srcid (uid/ipid) will be given the 'spammer' al2. + my($check_type, $srcid, $table_clause, $where_clause) = (undef, undef); + if (!isAnon($submitter_uid)) { + # Logged-in user, check by uid. + $check_type = 'uid'; + $srcid = $submitter_uid; + $table_clause = ''; + $where_clause = "firehose.uid = $submitter_uid"; + } elsif ($submitter_ipid) { + # Non-logged-in user, check by IP (submissions.ipid) + $check_type = 'ipid'; + $srcid = convert_srcid('ipid', $submitter_ipid); + $table_clause = ', globjs, submissions'; + $where_clause = "firehose.type='submission' + AND firehose.globjid=globjs.globjid + AND globjs.target_id=submissions.subid + AND submissions.ipid='$submitter_ipid'"; } -} + # If neither of the above, it's an anonymous non-submission, so + # (at present) there's nothing we will do to block its "fellow" + # firehose items. -sub despam_srcid { - my($self, $srcid, $count) = @_; - my $slashdb = getCurrentDB(); - my $constants = getCurrentStatic(); + # Find out which and how many other 'binspam' tags this contributor + # has amassed in total (where "contributor" can be an ipid or uid). + my $binspam_tagid_globj_hr = { }; + if ($check_type) { + $binspam_tagid_globj_hr = $slashdb->sqlSelectAllKeyValue( + 'tags.tagid, tags.globjid', + "tags, firehose$table_clause", + "tags.globjid = firehose.globjid + AND tags.tagnameid = $self->{spamid} + AND tags.uid IN ($admin_in_str) + AND tags.inactivated IS NULL + AND $where_clause"); + } - my $al2_hr = $slashdb->getAL2($srcid); - if ($count > $constants->{tagbox_despam_binspamsallowed_ip}) { - main::tagboxLog("marking $srcid as spammer for $count"); - if (!$al2_hr->{spammer}) { - $slashdb->setAL2($srcid, { spammer => 1, comment => "Despam $count" }); - } + # This array contains the list of admin tags applied to + # firehose items from this srcid. If there are too many + # of them, mark the srcid. + my $binspam_count = scalar(keys %$binspam_tagid_globj_hr); + my $mark_srcid = 0; + if ($binspam_count > + ( $check_type eq 'uid' + ? $constants->{tagbox_despam_binspamsallowed} + : $constants->{tagbox_despam_binspamsallowed_ip} ) + ) { + $is_spam = $mark_srcid = 1; } -} -sub despam_uid { - my($self, $uid, $count) = @_; - my $constants = getCurrentStatic(); - my $slashdb = getCurrentDB(); - my $reader = getObject('Slash::DB', { db_type => 'reader' }); - my $tagboxdb = getObject('Slash::Tagbox'); + main::tagboxLog(sprintf("%s->run uid=%d ipid=%s check_type=%s affected_id=%d srcid=%s count=%d is_spam=%d mark_srcid=%d tagids: '%s'", + ref($self), ($submitter_uid || '0'), ($submitter_ipid || 'none'), + (defined($check_type) ? $check_type : 'undef'), + $affected_id, $srcid, $binspam_count, $is_spam, $mark_srcid, + join(' ', sort { $a <=> $b } keys %$binspam_tagid_globj_hr))); - # First, set the user's 'spammer' AL2. - my $adminuid = $constants->{tagbox_despam_al2adminuid}; - my $al2_hr = $slashdb->getAL2($uid); - if (!$al2_hr->{spammer}) { - $slashdb->setAL2($uid, { spammer => 1, comment => "Despam $count" }, - { adminuid => $adminuid }); + # is_spam=0 is_spam=1 mark_srcid=1 + # + # check_type undef clear 1 globj set 1 globjid set 1 globjid + # check_type=uid clear 1 globj set 1 globjid set all globjids, setAL2 + # check_type=ipid clear 1 globj set 1 globjid set all globjids, setAL2 + + # Always set/clear at least the one globjid affected. + my %globjids = ( $affected_id, 1 ); + if ($mark_srcid && $check_type) { + # Set/clear both the individual globjid and all its + # fellow submitted globjids, if known. + for my $tagid (keys %$binspam_tagid_globj_hr) { + $globjids{ $binspam_tagid_globj_hr->{$tagid} } = 1; + } } + # Convert that list of globjids to firehose ids. + my $globjid_in_str = join(',', sort { $a <=> $b } keys %globjids); + my $fhid_hr = $slashdb->sqlSelectAllKeyValue( + 'id, globjid', + 'firehose', + "globjid IN ($globjid_in_str)"); + main::tagboxLog(sprintf("%s->run globjids '%s' -> fhids '%s'", + ref($self), + join(' ', sort { $a <=> $b } keys %globjids), + join(' ', sort { $a <=> $b } keys %$fhid_hr))); - # Next, set the user's clout manually to 0. - $slashdb->setUser($uid, { tag_clout => 0 }); - - # Next, mark as spam everything the user's submitted. - $slashdb->sqlUpdate('firehose', { is_spam => 'yes' }, - "accepted != 'no' AND uid=$uid"); - - # Next, if $count is high enough, set the 'spammer' AL2 for all - # the IPID's the user has submitted from. - if ($count > $constants->{tagbox_despam_binspamsallowed_ip}) { - my $days = defined($constants->{tagbox_despam_ipdayslookback}) - ? $constants->{tagbox_despam_ipdayslookback} : 60; - my %srcid_used = ( ); - if ($days) { - my $sub_ipid_ar = $reader->sqlSelectColArrayref( - 'DISTINCT ipid', - 'submissions', - "uid=$uid AND time >= DATE_SUB(NOW(), INTERVAL $days DAY) AND ipid != ''"); - my $journal_srcid_ar = $reader->sqlSelectColArrayref( - 'DISTINCT ' . get_srcid_sql_out('srcid_32'), - 'journals', - "uid=$uid AND date >= DATE_SUB(NOW(), INTERVAL $days DAY) AND srcid_32 != 0"); - my $book_srcid_ar = $reader->sqlSelectColArrayref( - 'DISTINCT ' . get_srcid_sql_out('srcid_32'), - 'bookmarks', - "uid=$uid AND createdtime >= DATE_SUB(NOW(), INTERVAL $days DAY) AND srcid_32 != 0"); - for my $ipid (@$sub_ipid_ar) { - my $srcid = convert_srcid(ipid => $ipid); - $srcid_used{$srcid} = 1; + # Loop on all the fhids required to be changed, setting or + # clearing them as appropriate. + for my $fhid (sort { $a <=> $b } keys %$fhid_hr) { + my $globjid = $fhid_hr->{$fhid}; + my $rows = $firehose_db->setFireHose($fhid, { is_spam => ($is_spam ? 'yes' : 'no') }); + main::tagboxLog(sprintf("%s->run marked fhid %d (%d) as is_spam=%d rows=%s", + ref($self), $fhid, $globjid, $is_spam, $rows)); + if ($rows > 0) { + # If this firehose item's spam status changed, either way, its + # scores now need to be recalculated immediately. + # Get the list of tbids we need to force a recalc for. + if (!defined $self->{recalc_tbids}) { + my $tagboxes = $tagboxdb->getTagboxes(); + for my $tagbox_hr (@$tagboxes) { + push @{$self->{recalc_tbids}}, $tagbox_hr->{tbid} + if $tagbox_hr->{name} =~ /^(FHEditorPop|FireHoseScores)$/; + } } - for my $srcid (@$journal_srcid_ar) { - $srcid_used{$srcid} = 1; + # Force the recalculations of their scores. + for my $tbid (@{$self->{recalc_tbids}}) { + $tagboxdb->forceFeederRecalc($tbid, $globjid); + main::tagboxLog(sprintf("%s->run force recalc tbid=%d globjid=%d", + ref($self), $tbid, $globjid)); } - for my $srcid (@$book_srcid_ar) { - $srcid_used{$srcid} = 1; - } - my @srcids = sort grep { $_ } keys %srcid_used; - for my $srcid (@srcids) { - $al2_hr = $slashdb->getAL2($srcid); - if (!$al2_hr->{spammer}) { - $slashdb->setAL2($srcid, { spammer => 1, comment => "Despam $count for $uid" }); - } - } } } - # Next, declout everyone who's upvoted any of the user's - # recent submissions (except bookmarks, because those are - # generic enough). - my $daysback = $constants->{tagbox_despam_decloutdaysback} || 7; - my $upvoter_ar = $slashdb->sqlSelectColArrayref( - 'DISTINCT tags.uid', - 'tags, firehose', - "tags.globjid = firehose.globjid - AND firehose.uid = $uid - AND type IN ('submission', 'journal') - AND createtime >= DATE_SUB(NOW(), INTERVAL $daysback DAY) - AND tagnameid = $self->{upvoteid} - AND inactivated IS NULL"); - my $max_clout = defined($constants->{tagbox_despam_upvotermaxclout}) - ? $constants->{tagbox_despam_upvotermaxclout} : '0.85'; - for my $upvoter (@$upvoter_ar) { - main::tagboxLog("setting user $upvoter clout to max $max_clout for upvoting user $uid"); - $slashdb->setUser($upvoter, { - -tag_clout => "MAX(tag_clout, $max_clout)" - }); + # If appropriate, mark the submitter's uid or ipid as a spammer + # and mark _all_ their submissions as binspam. + if ($mark_srcid && $check_type) { + main::tagboxLog(sprintf("%s->run marking spammer AL2 srcid=%s", + ref($self), $srcid)); + $slashdb->setAL2($srcid, { spammer => 1 }, { adminuid => 1183959 }); } - - # Next, insert tagboxlog_feeder entries to tell the relevant - # tagboxes to recalculate those scores. - my $tagboxes = $tagboxdb->getTagboxes(); - my @tagboxids = map { $_->{tbid} } grep { $_->{name} =~ /^(FHEditorPop|FireHoseScores)$/ } @$tagboxes; - my $globjid_tagid = $slashdb->sqlSelectAllKeyValue( - 'firehose.globjid, tagid', - 'firehose, tags', - "firehose.uid=$uid - AND firehose.globjid=tags.globjid - AND tags.uid=$uid - AND tagnameid=$self->{upvoteid}", - 'GROUP BY firehose.globjid'); - for my $globjid (sort keys %$globjid_tagid) { - for my $tbid (@tagboxids) { - $tagboxdb->addFeederInfo($tbid, { - affected_id => $globjid, - importance => 1, - tagid => $globjid_tagid->{ $globjid }, - }); - } - } } +#sub despam_srcid { +# my($self, $srcid, $count) = @_; +# my $slashdb = getCurrentDB(); +# my $constants = getCurrentStatic(); +# +# my $al2_hr = $slashdb->getAL2($srcid); +# if ($count > $constants->{tagbox_despam_binspamsallowed_ip}) { +# main::tagboxLog("marking $srcid as spammer for $count"); +# if (!$al2_hr->{spammer}) { +# $slashdb->setAL2($srcid, { spammer => 1, comment => "Despam $count" }); +# } +# } +#} +# +#sub despam_uid { +# my($self, $uid, $count) = @_; +# my $constants = getCurrentStatic(); +# my $slashdb = getCurrentDB(); +# my $reader = getObject('Slash::DB', { db_type => 'reader' }); +# my $tagboxdb = getObject('Slash::Tagbox'); +# +# # First, set the user's 'spammer' AL2. +# my $adminuid = $constants->{tagbox_despam_al2adminuid}; +# my $al2_hr = $slashdb->getAL2($uid); +# if (!$al2_hr->{spammer}) { +# $slashdb->setAL2($uid, { spammer => 1, comment => "Despam $count" }, +# { adminuid => $adminuid }); +# } +# +# # Next, set the user's clout manually to 0. +# $slashdb->setUser($uid, { tag_clout => 0 }); +# +# # Next, mark as spam everything the user's submitted. +# $slashdb->sqlUpdate('firehose', { is_spam => 'yes' }, +# "accepted != 'no' AND uid=$uid"); +# +# # Next, if $count is high enough, set the 'spammer' AL2 for all +# # the IPID's the user has submitted from. +# if ($count > $constants->{tagbox_despam_binspamsallowed_ip}) { +# my $days = defined($constants->{tagbox_despam_ipdayslookback}) +# ? $constants->{tagbox_despam_ipdayslookback} : 60; +# my %srcid_used = ( ); +# if ($days) { +# my $sub_ipid_ar = $reader->sqlSelectColArrayref( +# 'DISTINCT ipid', +# 'submissions', +# "uid=$uid AND time >= DATE_SUB(NOW(), INTERVAL $days DAY) AND ipid != ''"); +# my $journal_srcid_ar = $reader->sqlSelectColArrayref( +# 'DISTINCT ' . get_srcid_sql_out('srcid_32'), +# 'journals', +# "uid=$uid AND date >= DATE_SUB(NOW(), INTERVAL $days DAY) AND srcid_32 != 0"); +# my $book_srcid_ar = $reader->sqlSelectColArrayref( +# 'DISTINCT ' . get_srcid_sql_out('srcid_32'), +# 'bookmarks', +# "uid=$uid AND createdtime >= DATE_SUB(NOW(), INTERVAL $days DAY) AND srcid_32 != 0"); +# for my $ipid (@$sub_ipid_ar) { +# my $srcid = convert_srcid(ipid => $ipid); +# $srcid_used{$srcid} = 1; +# } +# for my $srcid (@$journal_srcid_ar) { +# $srcid_used{$srcid} = 1; +# } +# for my $srcid (@$book_srcid_ar) { +# $srcid_used{$srcid} = 1; +# } +# my @srcids = sort grep { $_ } keys %srcid_used; +# for my $srcid (@srcids) { +# $al2_hr = $slashdb->getAL2($srcid); +# if (!$al2_hr->{spammer}) { +# $slashdb->setAL2($srcid, { spammer => 1, comment => "Despam $count for $uid" }); +# } +# } +# } +# } +# +# # Next, declout everyone who's upvoted any of the user's +# # recent submissions (except bookmarks, because those are +# # generic enough). +# my $daysback = $constants->{tagbox_despam_decloutdaysback} || 7; +# my $upvoter_ar = $slashdb->sqlSelectColArrayref( +# 'DISTINCT tags.uid', +# 'tags, firehose', +# "tags.globjid = firehose.globjid +# AND firehose.uid = $uid +# AND type IN ('submission', 'journal') +# AND createtime >= DATE_SUB(NOW(), INTERVAL $daysback DAY) +# AND tagnameid = $self->{upvoteid} +# AND inactivated IS NULL"); +# my $max_clout = defined($constants->{tagbox_despam_upvotermaxclout}) +# ? $constants->{tagbox_despam_upvotermaxclout} : '0.85'; +# for my $upvoter (@$upvoter_ar) { +# main::tagboxLog("setting user $upvoter clout to max $max_clout for upvoting user $uid"); +# $slashdb->setUser($upvoter, { +# -tag_clout => "MAX(tag_clout, $max_clout)" +# }); +# } +# +# # Next, insert tagboxlog_feeder entries to tell the relevant +# # tagboxes to recalculate those scores. +# my $tagboxes = $tagboxdb->getTagboxes(); +# my @tagboxids = map { $_->{tbid} } grep { $_->{name} =~ /^(FHEditorPop|FireHoseScores)$/ } @$tagboxes; +# my $globjid_tagid = $slashdb->sqlSelectAllKeyValue( +# 'firehose.globjid, tagid', +# 'firehose, tags', +# "firehose.uid=$uid +# AND firehose.globjid=tags.globjid +# AND tags.uid=$uid +# AND tagnameid=$self->{upvoteid}", +# 'GROUP BY firehose.globjid'); +# for my $globjid (sort keys %$globjid_tagid) { +# for my $tbid (@tagboxids) { +# $tagboxdb->addFeederInfo($tbid, { +# affected_id => $globjid, +# importance => 1, +# tagid => $globjid_tagid->{ $globjid }, +# }); +# } +# } +#} + 1; Modified: slashjp/branches/upstream/current/themes/slashcode/THEME =================================================================== --- slashjp/branches/upstream/current/themes/slashcode/THEME 2008-03-31 12:09:17 UTC (rev 559) +++ slashjp/branches/upstream/current/themes/slashcode/THEME 2008-04-01 03:35:14 UTC (rev 560) @@ -1,4 +1,4 @@ -# $Id: THEME,v 1.129 2008/02/21 01:01:52 pudge Exp $ +# $Id: THEME,v 1.131 2008/03/14 17:57:33 scc Exp $ name=slashcode description="Slashcode.com theme" topic=htdocs/images/topics/topicbug.jpg @@ -127,7 +127,6 @@ htdoc=htdocs/topics.pl htdoc=htdocs/users.pl htdoc=htdocs/images/comments.js -htdoc=htdocs/images/comments2.js htdoc=htdocs/images/dumper.js htdoc=htdocs/badge.pl htdoc=htdocs/help.pl @@ -340,6 +339,7 @@ plugin=Login plugin=Hof plugin=Messages +plugin=Moderation plugin=PollBooth plugin=Print plugin=PubKey Modified: slashjp/branches/upstream/current/themes/slashcode/htdocs/comments.pl =================================================================== --- slashjp/branches/upstream/current/themes/slashcode/htdocs/comments.pl 2008-03-31 12:09:17 UTC (rev 559) +++ slashjp/branches/upstream/current/themes/slashcode/htdocs/comments.pl 2008-04-01 03:35:14 UTC (rev 560) @@ -2,7 +2,7 @@ # This code is a part of Slash, and is released under the GPL. # Copyright 1997-2005 by Open Source Technology Group. See README # and COPYING for more information, or see http://slashcode.com/. -# $Id: comments.pl,v 1.270 2008/02/28 19:26:58 pudge Exp $ +# $Id: comments.pl,v 1.272 2008/03/20 07:30:29 pudge Exp $ use strict; use Slash 2.003; # require Slash 2.3.x @@ -203,7 +203,7 @@ header($title, $section) or return; $header_emitted = 1; } - print getError('login error'); + print Slash::Utility::Comments::getError('login error'); $op = 'preview'; } $op = 'default' if @@ -217,7 +217,7 @@ header($title, $section) or return; $header_emitted = 1; } - print getError("nosubscription"); + print Slash::Utility::Comments::getError("nosubscription"); } #print STDERR scalar(localtime) . " $$ B op=$op header_emitted=$header_emitted\n"; @@ -369,18 +369,6 @@ return fixurl($uri); } -################################################################# -# this groups all the errors together in -# one template, called "errors;comments;default" -# Why not just getData??? -Brian -sub getError { - my($value, $hashref, $nocomm) = @_; - $hashref ||= {}; - $hashref->{value} = $value; - return slashDisplay('errors', $hashref, - { Return => 1, Nocomm => $nocomm }); -} - ################################################################## sub delete { my($form, $slashdb, $user, $constants) = @_; @@ -449,7 +437,7 @@ if ($sid) { $sid =~ /(\d+)/; $sid = $1 } if (!$sid) { # Need a discussion ID to reply to, or there's no point. - print getError('no sid'); + print Slash::Utility::Comments::getError('no sid'); return; } @@ -461,7 +449,7 @@ # An attempt to reply to a comment that doesn't exist is an error. if ($pid && !%$reply) { - print getError('no such parent'); + print Slash::Utility::Comments::getError('no such parent'); return; } elsif ($pid) { $pid_reply = prepareQuoteReply($reply); @@ -485,12 +473,12 @@ # just in case the user fudged it. if (($user->{is_anon} || $form->{postanon}) && !$slashdb->checkAllowAnonymousPosting($user->{uid})) { - print getError('anonymous disallowed'); + print Slash::Utility::Comments::getError('anonymous disallowed'); return; } if ($discussion->{type} eq 'archived') { - print getError('archive_error'); + print Slash::Utility::Comments::getError('archive_error'); return; } @@ -498,12 +486,7 @@ $preview = previewForm(\$error_message, $discussion) or $error_flag++; } - if (%$reply && !$form->{postersubj}) { - $form->{postersubj} = decode_entities($reply->{subject}); - $form->{postersubj} =~ s/^Re://i; - $form->{postersubj} =~ s/\s\s/ /g; - $form->{postersubj} = "Re:$form->{postersubj}"; - } + preProcessReplyForm($form, $reply); my $extras = []; my $disc_skin = $slashdb->getSkin($discussion->{primaryskid}); @@ -514,8 +497,10 @@ if $disc_skin && $disc_skin->{nexus}; my $gotmodwarning; - $gotmodwarning = 1 if $form->{gotmodwarning} - || $error_message && $error_message eq getError("moderations to be lost"); + $gotmodwarning = 1 if $form->{gotmodwarning} || + ($error_message && $error_message eq + Slash::Utility::Comments::getError("moderations to be lost") + ); slashDisplay('edit_comment', { pid_reply => $pid_reply, @@ -542,7 +527,7 @@ my $comment = preProcessComment($form, $user, $discussion, $error_message) or return; return $$error_message if $comment eq '-1'; - my $preview = postProcessComment({ %$comment, %$user }, 0, $discussion); + my $preview = postProcessComment({ %$user, %$form, %$comment }, 0, $discussion); if ($constants->{plugin}{Subscribe}) { $preview->{subscriber_bonus} = @@ -685,9 +670,9 @@ # went wrong. if ($ret_val < 0) { if ($ret_val == -1) { - print getError('no points'); + print Slash::Utility::Comments::getError('no points'); } elsif ($ret_val == -2){ - print getError('not enough points'); + print Slash::Utility::Comments::getError('not enough points'); } } else { $was_touched += $ret_val; Modified: slashjp/branches/upstream/current/themes/slashcode/htdocs/images/comments.js =================================================================== (Binary files differ) Deleted: slashjp/branches/upstream/current/themes/slashcode/htdocs/images/comments2.js =================================================================== (Binary files differ) Modified: slashjp/branches/upstream/current/themes/slashcode/htdocs/images/dumper.js =================================================================== (Binary files differ) Modified: slashjp/branches/upstream/current/themes/slashcode/templates/dispComment;misc;default =================================================================== --- slashjp/branches/upstream/current/themes/slashcode/templates/dispComment;misc;default 2008-03-31 12:09:17 UTC (rev 559) +++ slashjp/branches/upstream/current/themes/slashcode/templates/dispComment;misc;default 2008-04-01 03:35:14 UTC (rev 560) @@ -34,7 +34,7 @@ [% ELSE %] <h4><a name="[% cid %]">[% subject %]</a> [%- END %] - [% UNLESS user.noscores %]<span id="comment_score_[% cid %]" class="score">(Score:[% IF points.length; points; ELSE; "?"; END %][% IF reasons && reason %], [% reasons.$reason.name %][% END %])</span>[% END %]</h4> + [% UNLESS user.noscores %]<span id="comment_score_[% cid %]" class="score">([% IF constants.modal_prefs_active && !user.is_anon %]<a href="#" onclick="getModalPrefs('modcommentlog', 'Moderation Comment Log', [% cid %]); return false">[% END %]Score:[% points.length ? points : "?" %][% IF constants.modal_prefs_active && !user.is_anon %]</a>[% END %][% IF reasons && reason %], [% reasons.$reason.name %][% END %])</span>[% END %]</h4> </div> <div class="details"> by @@ -81,4 +81,4 @@ __seclev__ 10000 __version__ -$Id: dispComment;misc;default,v 1.64 2007/10/25 02:12:17 pudge Exp $ +$Id: dispComment;misc;default,v 1.66 2008/03/19 08:25:31 pudge Exp $ Modified: slashjp/branches/upstream/current/themes/slashcode/templates/dispLinkComment;misc;default =================================================================== --- slashjp/branches/upstream/current/themes/slashcode/templates/dispLinkComment;misc;default 2008-03-31 12:09:17 UTC (rev 559) +++ slashjp/branches/upstream/current/themes/slashcode/templates/dispLinkComment;misc;default 2008-04-01 03:35:14 UTC (rev 560) @@ -22,14 +22,14 @@ [ [% IF !user.state.discussion_archived && !user.state.discussion_future_nopost %] - [% Slash.linkComment({ + <span id="reply_link_[% cid %]">[% Slash.linkComment({ sid => sid, pid => cid, op => 'Reply', subject => 'Reply to This', subject_only => 1, - onclick => ((discussion2 && user.test_code) ? "replyTo($cid); return false;" : '') - }) %] + onclick => ((discussion2 && (!constants.subscribe || user.is_subscriber)) ? "replyTo($cid); return false;" : '') + }) %]</span> [% END %] [% IF !(user.state.discussion_archived) && ( do_parent || can_mod || can_del ) %] | [% END %] @@ -68,4 +68,4 @@ __seclev__ 10000 __version__ -$Id: dispLinkComment;misc;default,v 1.40 2008/02/28 19:26:58 pudge Exp $ +$Id: dispLinkComment;misc;default,v 1.43 2008/03/19 21:09:47 pudge Exp $ Modified: slashjp/branches/upstream/current/themes/slashcode/templates/dispStory;misc;default =================================================================== --- slashjp/branches/upstream/current/themes/slashcode/templates/dispStory;misc;default 2008-03-31 12:09:17 UTC (rev 559) +++ slashjp/branches/upstream/current/themes/slashcode/templates/dispStory;misc;default 2008-04-01 03:35:14 UTC (rev 560) @@ -71,7 +71,7 @@ [% mypagemenu = PROCESS pagemenu; IF mypagemenu %]<br>[% mypagemenu %][% END %] <div class="topic"> [% seen_topics.${topic.tid} = 1 %] - [% IF user.noicons || user.simpledesign || user.lowbandwidth %] + [% IF user.noicons || user.simpledesign || user.lowbandwidth || user.pda %] [ <a href="[% gSkin.rootdir %]/search.pl?tid=[% topic.tid %]">[% topic.textname %]</a> ] [% ELSIF topic.image %] <a href="[% gSkin.rootdir %]/search.pl?tid=[% topic.tid %]"> @@ -95,7 +95,17 @@ [% story.introtext %] </div> -[% IF full && user.is_admin && !preview && env.script_name != '/admin.pl' %]<br><a href="[% gSkin.rootdir -%]/admin.pl?op=edit&sid=[% story.sid %]">[ Edit ]</a> [% IF constants.plugin.Ajax %][% PROCESS signoff stoid = story.stoid %] [% PROCESS neverdisplay stoid = stoid %][% END %][% END %] +[% IF full && user.is_admin && !preview && env.script_name != '/admin.pl' %]<br><a href="[% gSkin.rootdir -%]/admin.pl?op=edit&sid=[% story.sid %]">[ Edit ]</a> [% END %] +[% IF full && !preview && env.script_name != '/admin.pl' %] + [% IF constants.plugin.Ajax %] + [% IF user.is_admin || user.acl.signoff_allowed %] + [% PROCESS signoff stoid = story.stoid %] + [% END %] + [% IF user.is_admin %] + [% PROCESS neverdisplay stoid = stoid %] + [% END %] + [% END %] +[% END %] [% IF story.is_future && !user.is_admin %]<p>See any serious problems with this story? [% IF constants.ircslash_remarks %] @@ -164,4 +174,4 @@ __seclev__ 10000 __version__ -$Id: dispStory;misc;default,v 1.67 2007/10/24 00:30:08 scc Exp $ +$Id: dispStory;misc;default,v 1.69 2008/03/18 20:33:39 tvroom Exp $ Modified: slashjp/branches/upstream/current/themes/slashcode/templates/errors;comments;default =================================================================== --- slashjp/branches/upstream/current/themes/slashcode/templates/errors;comments;default 2008-03-31 12:09:17 UTC (rev 559) +++ slashjp/branches/upstream/current/themes/slashcode/templates/errors;comments;default 2008-04-01 03:35:14 UTC (rev 560) @@ -34,7 +34,7 @@ to do so, because open proxies are used to spam web boards like this one. [% IF constants.comments_portscan!=2 %]If you really can't close it and still want to post, you'll have to <a href="[% gSkin.rootdir %]/users.pl">register and log in</a>.[% END %] -<p>If you have questions, mention that your proxy is at +If you have questions, mention that your proxy is at <tt>[% unencoded_ip %]</tt> on port <tt>[% port %]</tt>. [% # COMMENT TABLE NOT AVAILABLE FOR WRITING @@ -69,133 +69,128 @@ [% # NO POINTS. CASE "no points" %] -You don't have any moderator points.<br> +You don't have any moderator points. [% # NO POINTS. CASE "not enough points" %] -You don't have enough moderator points.<br> +You don't have enough moderator points. [% # COMMENTS MAX POSTS. CASE "comments max posts" %] -<br><p><b>You've reached your maximum number of comments you can post: [% max_posts %] comments over [% timeframe %]. -</b></p> +You've reached your maximum number of comments you can post: [% max_posts %] comments over [% timeframe %]. [% # COMMENTS MAX POSTS. CASE "discussions max posts" %] -<br><p><b>You've reached your maximum number of discussions you can submit: [% max_posts %] discussions over [% timeframe %]. -</b></p> +You've reached your maximum number of discussions you can submit: [% max_posts %] discussions over [% timeframe %]. [% # INVALID FORMKEY CASE "invalid formkey" %] -[% PROCESS titlebar width="100%" title="Invalid form key!" %] -<br><p><b>form key: [% formkey %] !</b></p> +[% PROCESS titlebar width="100%" title="Invalid form key!" UNLESS no_titlebar %] +Invalid form key: [% formkey %]! [% # RESPONSE LIMIT CASE "comments response limit" %] -[% PROCESS titlebar width="100%" title="Slow Down Cowboy!" %] -<p>[% constants.sitename %] requires you to wait [% limit %] between -hitting 'reply' and submitting a comment.</p> -<p>It's been [% response %] since you hit 'reply'!</p> +[% PROCESS titlebar width="100%" title="Slow Down Cowboy!" UNLESS no_titlebar %] +[% constants.sitename %] requires you to wait [% limit %] between hitting 'Reply' +and submitting a comment. It's been [% response %] since you hit 'Reply.' [% # POST LIMIT CASE "comments post limit" %] -[% PROCESS titlebar width="100%" title="Slow Down Cowboy!" %] -<p>[% constants.sitename %] requires you to wait between -each successful posting of a comment to allow everyone a fair chance -at posting a comment.</p> -<p>It's been [% interval %] since you last successfully posted a comment.</p> +[% PROCESS titlebar width="100%" title="Slow Down Cowboy!" UNLESS no_titlebar %] +[% constants.sitename %] requires you to wait between each successful posting of +a comment to allow everyone a fair chance at posting a comment. It's been +[% interval %] since you last successfully posted a comment. [% # POST LIMIT CASE "discussions post limit" %] -[% PROCESS titlebar width="100%" title="Slow Down Cowboy!" %] -<p>[% constants.sitename %] requires you to wait between -each successful creation of a discussion .</p> -<p>It's been [% interval %] since you last successfully created a discussion.</p> +[% PROCESS titlebar width="100%" title="Slow Down Cowboy!" UNLESS no_titlebar %] +[% constants.sitename %] requires you to wait between each successful creation +of a discussion. It's been [% interval %] since you last successfully created a discussion. + [% # USED FORM CASE "used form" %] -[% PROCESS titlebar width="100%" title="Form Error!" %] +[% PROCESS titlebar width="100%" title="Form Error!" UNLESS no_titlebar %] This form has been used already to submit a comment [% interval %] ago. You can not use a form and hit the back button to use it again. [% # READ ONLY CASE "readonly" %] -<br><b>You can't post to this page.</b><br> +You can't post to this page. [% # TOO MANY POSTS CASE "comments post limit daily" %] -[% PROCESS titlebar width="100%" title="Call It A Night, Cowboy!" %] -<p>[% constants.sitename %] only allows -[% IF user.is_anon; "anonymous users"; -ELSE; "a user with your karma"; END %] -to post [% limit %] times per day (more or less, depending on -moderation). -[% IF user.is_anon; "A user from your IP has already shared his or her thoughts"; -ELSE; "You've already shared your thoughts"; END %] +[% PROCESS titlebar width="100%" title="Call It A Night, Cowboy!" UNLESS no_titlebar %] +[% constants.sitename %] only allows +[% IF user.is_anon; + "anonymous users"; +ELSE; + "a user with your karma"; END %] +to post [% limit %] times per day (more or less, depending on moderation). + +[% IF user.is_anon; + "A user from your IP has already shared his or her thoughts"; +ELSE; + "You've already shared your thoughts"; END %] with us that many times. Take a breather, and come back and see us in 24 hours or so. -<p>If you think this is unfair, please email -[% IF constants.adminmail_post; constants.adminmail_post; -ELSE; constants.adminmail; END %] -with your + +If you think this is unfair, please email +[% constants.adminmail_post || constants.adminmail %] with your [% IF user.is_anon %] -MD5'd IPID, which is <tt>[% user.ipid %]</tt>[% -ELSE %] -username "<tt>[% user.nickname | strip_literal %]</tt>"[% -END %]. Let us know how many comments <em>you</em> think you've -posted in the last 24 hours. + MD5'd IPID, which is <tt>[% user.ipid %]</tt>[% ELSE %] + username "<tt>[% user.nickname | strip_literal %]</tt>"[% END %]. +Let us know how many comments <em>you</em> think you've posted in the last 24 hours. + + [% # TROLL MESSAGE. CASE "troll message" %] Due to excessive bad posting from this IP or Subnet, [% IF logged_in_allowed -%]anonymous [% END %]comment posting -has temporarily been disabled. +%]anonymous [% END %]comment posting has temporarily been disabled. + [% IF logged_in_allowed %] You can still login to post. However, if bad posting continues from your IP or Subnet that privilege could be revoked as well. [% END %] -If it's you, consider this a chance to -sit in the timeout corner[% IF logged_in_allowed %] or login and improve your posting[% END %] -. If it's someone else, this is a chance to hunt them down. -If you think this is unfair, please email -[% IF constants.adminmail_mod; constants.adminmail_mod; -ELSE; constants.adminmail; END %] -with your MD5'd IPID and SubnetID, which are -"<tt>[% user.ipid %]</tt>" and "<tt>[% user.subnetid %]</tt>"[% -IF !user.is_anon %] -and (optionally, but preferably) your IP number -"<tt>[% unencoded_ip %]</tt>" and your username "<tt>[% user.nickname | strip_literal %]</tt>"[% -END %]. +If it's you, consider this a chance to sit in the timeout +corner[% IF logged_in_allowed %] or login and improve your posting[% END %]. +If it's someone else, this is a chance to hunt them down. If you think this is +unfair, please email [% constants.adminmail_mod || constants.adminmail %] +with your MD5'd IPID and SubnetID, which are "<tt>[% user.ipid %]</tt>" and +"<tt>[% user.subnetid %]</tt>"[% IF !user.is_anon %] + and (optionally, but preferably) your IP number + "<tt>[% unencoded_ip %]</tt>" and your username + "<tt>[% user.nickname | strip_literal %]</tt>"[% END %]. + [% CASE "broken html" %] Your comment could not be processed. Please try again. [% # LOW CHARS-PER-LINE CASE "low chars-per-line" %] -Your comment has too few characters per line (currently [% ratio %]).<br> +Your comment has too few characters per line (currently [% ratio %]). [% # FILTER MESSAGE. CASE "filter message" %] -[% PROCESS titlebar width="100%" title="Lameness filter encountered. Post aborted!" %] +[% PROCESS titlebar width="100%" title="Lameness filter encountered. Post aborted!" UNLESS no_titlebar %] [% IF err_message %] -<b>Reason: [% err_message %]</b><br> +Filter error: [% err_message %] [% END %] [% # COMPRESS FILTER. CASE "compress filter" %] -[% PROCESS titlebar width="100%" title="Lameness filter encountered." %] -Your comment violated the "[% ratio %]" compression filter. Try less -whitespace and/or less repetition[% -IF ratio == 'postersubj' %] in the subject line[% END %]. -<b>Comment aborted.</b> +[% PROCESS titlebar width="100%" title="Lameness filter encountered." UNLESS no_titlebar %] +Your comment violated the "[% ratio %]" compression filter. Try less whitespace +and/or less repetition[% IF ratio == 'postersubj' %] in the subject line[% END %]. [% # SUBMISSION ERROR. CASE "submission error" %] -<p>There was an unknown error in the submission.<br> +There was an unknown error in the submission. [% # MAXCID EXCEEDED. CASE "maxcid exceeded" %] -Don't you have anything better to do with your life?<br> +Don't you have anything better to do with your life? [% # DUPLICATION ERROR. CASE "duplication error" %] @@ -214,31 +209,30 @@ form [% formname %] [% formkey %] already submitted [% CASE "seclevtoolow" %] -[% PROCESS titlebar width="100%" title="No permissions" %] +[% PROCESS titlebar width="100%" title="No permissions" UNLESS no_titlebar %] You do not have appropriate permissions to perform that action. [% CASE "nosubscription" %] -[% PROCESS titlebar width="100%" title="Not subscriber, or not subscribed page" %] -You can't see this discussion because it's scheduled in the future, -where only subscribers can see it.<p> -Either you are not a subscriber to [% constants.sitename %], or you -have indicated you don't want comments pages ad-free, or you have -set your daily limit of ad-free pages to lower than -the default [% constants.subscribe_hits_btmd %]. -Any of these three possible issues can be resolved at -<a href="[% gSkin.rootdir %]/subscribe.pl">your subscription page</a>.<p> +[% PROCESS titlebar width="100%" title="Not subscriber, or not subscribed page" UNLESS no_titlebar %] +You can't see this discussion because it's scheduled in the future, where only +subscribers can see it. Either you are not a subscriber to +[% constants.sitename %], or you have indicated you don't want comments pages +ad-free, or you have set your daily limit of ad-free pages to lower than the +default [% constants.subscribe_hits_btmd %]. Any of these three possible +issues can be resolved at <a href="[% gSkin.rootdir %]/subscribe.pl">your +subscription page</a>. [% CASE "moderations to be lost" %] -[% PROCESS titlebar width="100%" title="You've Already Moderated this Discussion" %] +[% PROCESS titlebar width="100%" title="You've Already Moderated this Discussion" UNLESS no_titlebar %] If you continue to post this comment, all moderations done to this discussion will be undone! Are you sure you want to post? [% # NO DISCUSSION ID SPECIFIED CASE "no sid" %] -[% PROCESS titlebar width="100%" title="No Discussion Specified" %] -You did not specify a discussion ID. If you clicked on a link internal -to [% constants.sitename %], this is a bug. If not, someone sent you -to a silly invalid URL. +[% PROCESS titlebar width="100%" title="No Discussion Specified" UNLESS no_titlebar %] +You did not specify a discussion ID. If you clicked on a link internal to +[% constants.sitename %], this is a bug. If not, someone sent you to a silly +invalid URL. [% CASE 'no_moderation' %] The moderation system is currently down. @@ -248,10 +242,10 @@ [% CASE %] -An unexpected error has occurred.<br><b>[% value %]</b><br> +An unexpected error has occurred: [% value %] [% END %] __seclev__ 1000 __version__ -$Id: errors;comments;default,v 1.39 2006/09/12 04:44:07 pudge Exp $ +$Id: errors;comments;default,v 1.42 2008/03/12 06:25:50 pudge Exp $ Modified: slashjp/branches/upstream/current/themes/slashcode/templates/html-header;misc;default =================================================================== --- slashjp/branches/upstream/current/themes/slashcode/templates/html-header;misc;default 2008-03-31 12:09:17 UTC (rev 559) +++ slashjp/branches/upstream/current/themes/slashcode/templates/html-header;misc;default 2008-04-01 03:35:14 UTC (rev 560) @@ -28,7 +28,7 @@ [% IF file.ie_cond %]<!--[if [% file.ie_cond %]]>[% END %]<link rel="[% file.rel %]" type="[% file.type %]" media="[% file.media %]" href="[% IF constants.css_use_imagedir; constants.imagedir; ELSE; constants.rootdir; END %]/[% file.file %]?[% constants.cvs_tag_currentcode %]"[% IF file.title %] title="[% file.title %]"[% END %]>[% IF file.ie_cond %]<![endif]-->[% END %] [% END -%] [%- IF constants.plugin.Ajax %] -<script src="[% constants.imagedir %]/prototype.js?[% constants.cvs_tag_currentcode %]" type="text/javascript"></script> +<script src="[% constants.imagedir %]/jquery-1.2.3.js?[% constants.cvs_tag_currentcode %]" type="text/javascript"></script> <script src="[% constants.imagedir %]/yui/yahoo.js?[% constants.cvs_tag_currentcode %]" type="text/javascript"></script> <script src="[% constants.imagedir %]/yui/dom.js?[% constants.cvs_tag_currentcode %]" type="text/javascript"></script> <script src="[% constants.imagedir %]/yui/event.js?[% constants.cvs_tag_currentcode %]" type="text/javascript"></script> @@ -56,4 +56,4 @@ __seclev__ 10000 __version__ -$Id: html-header;misc;default,v 1.38 2008/02/04 14:50:17 scc Exp $ +$Id: html-header;misc;default,v 1.39 2008/03/14 15:48:07 scc Exp $ Modified: slashjp/branches/upstream/current/themes/slashcode/templates/modCommentLog;misc;default =================================================================== --- slashjp/branches/upstream/current/themes/slashcode/templates/modCommentLog;misc;default 2008-03-31 12:09:17 UTC (rev 559) +++ slashjp/branches/upstream/current/themes/slashcode/templates/modCommentLog;misc;default 2008-04-01 03:35:14 UTC (rev 560) @@ -36,15 +36,17 @@ __template__ [% IF mod_admin %] [% +hr_shown = 0; mod_index = 0; down=0; cnt=0; m2_down=0; m2_count=0; m2_offside=0; +a_up=0; a_sum=0; a_count=0; up=0; sum=0; count=0; a_m2_count=0; a_down=0; a_cnt=0; a_m2_down=0; a_m2_up=0; m2_count=0; a_m2_offside=0; a_m2_unfair_votes=0; unanimous = 0; unresolved=0; show_uid_totals = (type == "uid" && (this_user.totalmods || this_user.downmods || this_user.upmods || this_user.m2unfair || this_user.m2unfairpercent || this_user.stirred)); bg_toggle = 0; %] [% IF mods.size > 0 || show_uid_totals %] - [% IF user.is_admin and need_m2_form %] - <form method="post" action="[% gSkin.rootdir %]/comments.pl"> + [% IF user.is_admin && need_m2_form %] + <form method="post"[% IF constants.modal_prefs_active %] id="modal_prefs"[% END %] action="[% gSkin.rootdir %]/comments.pl"> <div> [% END %] [% IF meta_mod_only %] @@ -53,7 +55,7 @@ [% total_cols = 6 %] [% IF title; extra = ""; - IF constants.m2; + IF constants.m2 && !constants.modal_prefs_active; show_m2s_op = show_m2s ? 0 : 1; self_url = PROCESS base_url_mod; url_tail = PROCESS state_url_mod override = { show_m2s => show_m2s_op}; @@ -84,8 +86,6 @@ <th align=left>Moderatee [% IF constants.m2 %]<span class="admin_data_label">/ Metamoderator</span>[% END %]</th> [% END %] </tr> - [% hr_shown = 0; - mod_index = 0; %] [% FOREACH moderation = mods %] [% IF constants.m2 && type == "cid" && constants.show_m2s_with_mods && show_m2s && constants.m2_multicount; prev_index = mod_index - 1; @@ -203,7 +203,13 @@ [% IF need_m2_button %] <tr class="data_hl1"><td colspan="[% total_cols %]" align="right"> <input type="hidden" name="op" value="moderate"> - <input type="submit" name="submit" value="MetaModerate"> [%# XXX really? %] + [%- IF constants.modal_prefs_active %] + <input type="hidden" name="formname" value="metamoderate"> + <input type="hidden" name="refreshable" value=""> + <input type="button" value="MetaModerate" onclick="saveModalPrefs()"> + [%- ELSE %] + <input type="submit" name="submit" value="MetaModerate"> + [%- END %] </td></tr> [% END %] [% END %] @@ -367,4 +373,4 @@ __seclev__ 10000 __version__ -$Id: modCommentLog;misc;default,v 1.49 2006/10/26 17:33:09 jamiemccarthy Exp $ +$Id: modCommentLog;misc;default,v 1.52 2008/03/19 08:25:31 pudge Exp $ Modified: slashjp/branches/upstream/current/themes/slashcode/templates/printCommComments;misc;default =================================================================== --- slashjp/branches/upstream/current/themes/slashcode/templates/printCommComments;misc;default 2008-03-31 12:09:17 UTC (rev 559) +++ slashjp/branches/upstream/current/themes/slashcode/templates/printCommComments;misc;default 2008-04-01 03:35:14 UTC (rev 560) @@ -71,7 +71,8 @@ [% Slash.linkComment(next, 1) %]>> [% END %] </div> - [% m1_classname = "Slash::" _ constants.m1_pluginname; + [% UNLESS constants.modal_prefs_active; + m1_classname = "Slash::" _ constants.m1_pluginname; moddb = Slash.getObject(m1_classname); IF moddb; moddb.dispModCommentLog('cid', cid, { @@ -82,6 +83,7 @@ need_m2_button => constants.m2, title => " " }); END; + END; # constants.modal_prefs_active %] [% END %] @@ -101,6 +103,7 @@ [% lcp %] [% IF discussion2 && !cid %] +<div id="replyto_0"></div> <div class="prev-next"><a href="#" onclick="ajaxFetchComments(0,1); return false"><span id="more_comments_num_a" class="hide">Check for more</span></a> [% UNLESS user.state.discussion_archived || user.state.discussion_future_nopost %] | [% Slash.linkComment({ @@ -108,7 +111,8 @@ cid => cid, op => 'reply', subject => 'Reply', - subject_only => 1 + subject_only => 1, + onclick => ((discussion2 && (!constants.subscribe || user.is_subscriber)) ? "replyTo(0); return false;" : '') }); END %] </div> @@ -155,4 +159,4 @@ __seclev__ 10000 __version__ -$Id: printCommComments;misc;default,v 1.64 2008/01/18 22:36:51 pudge Exp $ +$Id: printCommComments;misc;default,v 1.68 2008/03/19 21:09:47 pudge Exp $ Modified: slashjp/branches/upstream/current/themes/slashcode/templates/printCommentsMain;misc;default =================================================================== --- slashjp/branches/upstream/current/themes/slashcode/templates/printCommentsMain;misc;default 2008-03-31 12:09:17 UTC (rev 559) +++ slashjp/branches/upstream/current/themes/slashcode/templates/printCommentsMain;misc;default 2008-04-01 03:35:14 UTC (rev 560) @@ -201,7 +201,8 @@ cid => cid, op => 'reply', subject => 'Reply', - subject_only => 1 + subject_only => 1, + onclick => ((discussion2 && (!constants.subscribe || user.is_subscriber)) ? "replyTo(0); return false;" : '') }) %] [% END %] </span> @@ -285,7 +286,8 @@ cid => cid, op => 'reply', subject => 'Reply', - subject_only => 1 + subject_only => 1, + onclick => ((discussion2 && (!constants.subscribe || user.is_subscriber)) ? "replyTo(0); return false;" : '') }) %] [% END %] <div id="bindings-legend">Keybindings Beta<br> @@ -308,4 +310,4 @@ __seclev__ 10000 __version__ -$Id: printCommentsMain;misc;default,v 1.103 2008/01/31 19:24:59 pudge Exp $ +$Id: printCommentsMain;misc;default,v 1.106 2008/03/19 21:09:47 pudge Exp $