Merge branch '0.7.x' of git@gitorious.org:laconica/dev

Conflicts:
	README
	lib/router.php
This commit is contained in:
Evan Prodromou 2009-04-01 14:40:58 -04:00
commit 3bec08c878
30 changed files with 799 additions and 441 deletions

10
README
View File

@ -877,7 +877,7 @@ This section is a catch-all for site-wide variables.
name: the name of your site, like 'YourCompany Microblog'. name: the name of your site, like 'YourCompany Microblog'.
server: the server part of your site's URLs, like 'example.net'. server: the server part of your site's URLs, like 'example.net'.
path: The path part of your site's URLs, like 'mublog' or '/' path: The path part of your site's URLs, like 'mublog' or ''
(installed in root). (installed in root).
fancy: whether or not your site uses fancy URLs (see Fancy URLs fancy: whether or not your site uses fancy URLs (see Fancy URLs
section above). Default is false. section above). Default is false.
@ -1184,10 +1184,10 @@ newuser
Options with new users. Options with new users.
subscribe: nickname of a user account to automatically subscribe new default: nickname of a user account to automatically subscribe new
users to. Typically this would be system account for e.g. users to. Typically this would be system account for e.g.
service updates or announcements. Users are able to unsub service updates or announcements. Users are able to unsub
if they want. Default is null; no auto subscribe. if they want. Default is null; no auto subscribe.
welcome: nickname of a user account that sends welcome messages to new welcome: nickname of a user account that sends welcome messages to new
users. Can be the same as 'subscribe' account, although on users. Can be the same as 'subscribe' account, although on
busy servers it may be a good idea to keep that one just for busy servers it may be a good idea to keep that one just for

View File

@ -166,6 +166,50 @@ class PublicAction extends Action
$nav->show(); $nav->show();
} }
function showPageNotice()
{
$notice = Notice::publicStream(0, 1);
if (!$notice) {
$this->serverError(_('Could not retrieve public stream.'));
return;
}
// no notices in the public stream, let's get out of here
if ($notice->count()) {
return;
}
$message = _('This is the public timeline for %%site.name%% but noone has posted anything yet.') . ' ';
if (common_logged_in()) {
$message .= _('Be the first to post!');
/*
sprintf(_('You are logged in... %%%%site.name%%%% groups let you find and talk with ' .
'people of similar interests. After you join a group ' .
'you can send messages to all other members using the ' .
'syntax "!groupname". Don\'t see a group you like? Try ' .
'[searching for one](%%%%action.groupsearch%%%%) or ' .
'[start your own!](%%%%action.newgroup%%%%)'));
*/
}
else {
$message .= _('Why not [register an account](%%action.register%%) and be the first to post!');
/*
sprintf(_('You are not logged in... %%%%site.name%%%% groups let you find and talk with ' .
'people of similar interests. After you join a group ' .
'you can send messages to all other members using the ' .
'syntax "!groupname". Don\'t see a group you like? Try ' .
'[searching for one](%%%%action.groupsearch%%%%) or ' .
'[start your own!](%%%%action.newgroup%%%%)'));
*/
}
$this->elementStart('div', 'blankfiller');
$this->raw(common_markup_to_html($message));
$this->elementEnd('div');
}
/** /**
* Fill the content area * Fill the content area
* *
@ -207,9 +251,14 @@ class PublicAction extends Action
function showAnonymousMessage() function showAnonymousMessage()
{ {
$m = _('This is %%site.name%%, a [micro-blogging](http://en.wikipedia.org/wiki/Micro-blogging) service ' . if (! (common_config('site','closed') || common_config('site','inviteonly'))) {
'based on the Free Software [Laconica](http://laconi.ca/) tool. ' . $m = _('This is %%site.name%%, a [micro-blogging](http://en.wikipedia.org/wiki/Micro-blogging) service ' .
'[Join now](%%action.register%%) to share notices about yourself with friends, family, and colleagues! ([Read more](%%doc.help%%))'); 'based on the Free Software [Laconica](http://laconi.ca/) tool. ' .
'[Join now](%%action.register%%) to share notices about yourself with friends, family, and colleagues! ([Read more](%%doc.help%%))');
} else {
$m = _('This is %%site.name%%, a [micro-blogging](http://en.wikipedia.org/wiki/Micro-blogging) service ' .
'based on the Free Software [Laconica](http://laconi.ca/) tool.');
}
$this->elementStart('div', array('id' => 'anon_notice')); $this->elementStart('div', array('id' => 'anon_notice'));
$this->raw(common_markup_to_html($m)); $this->raw(common_markup_to_html($m));
$this->elementEnd('div'); $this->elementEnd('div');

View File

@ -181,13 +181,21 @@ class RecoverpasswordAction extends Action
function showRecoverForm() function showRecoverForm()
{ {
$this->elementStart('form', array('method' => 'post', $this->elementStart('form', array('method' => 'post',
'id' => 'recoverpassword', 'id' => 'form_password_recover',
'class' => 'form_settings',
'action' => common_local_url('recoverpassword'))); 'action' => common_local_url('recoverpassword')));
$this->elementStart('fieldset');
$this->element('legend', null, _('Password recover'));
$this->elementStart('ul', 'form_data');
$this->elementStart('li');
$this->input('nicknameoremail', _('Nickname or email'), $this->input('nicknameoremail', _('Nickname or email'),
$this->trimmed('nicknameoremail'), $this->trimmed('nicknameoremail'),
_('Your nickname on this server, ' . _('Your nickname on this server, ' .
'or your registered email address.')); 'or your registered email address.'));
$this->elementEnd('li');
$this->elementEnd('ul');
$this->submit('recover', _('Recover')); $this->submit('recover', _('Recover'));
$this->elementEnd('fieldset');
$this->elementEnd('form'); $this->elementEnd('form');
} }
@ -213,14 +221,24 @@ class RecoverpasswordAction extends Action
function showResetForm() function showResetForm()
{ {
$this->elementStart('form', array('method' => 'post', $this->elementStart('form', array('method' => 'post',
'id' => 'recoverpassword', 'id' => 'form_password_change',
'class' => 'form_settings',
'action' => common_local_url('recoverpassword'))); 'action' => common_local_url('recoverpassword')));
$this->elementStart('fieldset');
$this->element('legend', null, _('Password change'));
$this->hidden('token', common_session_token()); $this->hidden('token', common_session_token());
$this->elementStart('ul', 'form_data');
$this->elementStart('li');
$this->password('newpassword', _('New password'), $this->password('newpassword', _('New password'),
_('6 or more characters, and don\'t forget it!')); _('6 or more characters, and don\'t forget it!'));
$this->elementEnd('li');
$this->elementStart('li');
$this->password('confirm', _('Confirm'), $this->password('confirm', _('Confirm'),
_('Same as password above')); _('Same as password above'));
$this->elementEnd('li');
$this->elementEnd('ul');
$this->submit('reset', _('Reset')); $this->submit('reset', _('Reset'));
$this->elementEnd('fieldset');
$this->elementEnd('form'); $this->elementEnd('form');
} }

View File

@ -396,11 +396,18 @@ class ShowgroupAction extends Action
function showAnonymousMessage() function showAnonymousMessage()
{ {
$m = sprintf(_('**%s** is a user group on %%%%site.name%%%%, a [micro-blogging](http://en.wikipedia.org/wiki/Micro-blogging) service ' . if (!(common_config('site','closed') || common_config('site','inviteonly'))) {
'based on the Free Software [Laconica](http://laconi.ca/) tool. Its members share ' . $m = sprintf(_('**%s** is a user group on %%%%site.name%%%%, a [micro-blogging](http://en.wikipedia.org/wiki/Micro-blogging) service ' .
'short messages about their life and interests. '. 'based on the Free Software [Laconica](http://laconi.ca/) tool. Its members share ' .
'[Join now](%%%%action.register%%%%) to become part of this group and many more! ([Read more](%%%%doc.help%%%%))'), 'short messages about their life and interests. '.
'[Join now](%%%%action.register%%%%) to become part of this group and many more! ([Read more](%%%%doc.help%%%%))'),
$this->group->nickname); $this->group->nickname);
} else {
$m = sprintf(_('**%s** is a user group on %%%%site.name%%%%, a [micro-blogging](http://en.wikipedia.org/wiki/Micro-blogging) service ' .
'based on the Free Software [Laconica](http://laconi.ca/) tool. Its members share ' .
'short messages about their life and interests. '),
$this->group->nickname);
}
$this->elementStart('div', array('id' => 'anon_notice')); $this->elementStart('div', array('id' => 'anon_notice'));
$this->raw(common_markup_to_html($m)); $this->raw(common_markup_to_html($m));
$this->elementEnd('div'); $this->elementEnd('div');

View File

@ -535,10 +535,16 @@ class ShowstreamAction extends Action
function showAnonymousMessage() function showAnonymousMessage()
{ {
$m = sprintf(_('**%s** has an account on %%%%site.name%%%%, a [micro-blogging](http://en.wikipedia.org/wiki/Micro-blogging) service ' . if (!(common_config('site','closed') || common_config('site','inviteonly'))) {
'based on the Free Software [Laconica](http://laconi.ca/) tool. ' . $m = sprintf(_('**%s** has an account on %%%%site.name%%%%, a [micro-blogging](http://en.wikipedia.org/wiki/Micro-blogging) service ' .
'[Join now](%%%%action.register%%%%) to follow **%s**\'s notices and many more! ([Read more](%%%%doc.help%%%%))'), 'based on the Free Software [Laconica](http://laconi.ca/) tool. ' .
$this->user->nickname, $this->user->nickname); '[Join now](%%%%action.register%%%%) to follow **%s**\'s notices and many more! ([Read more](%%%%doc.help%%%%))'),
$this->user->nickname, $this->user->nickname);
} else {
$m = sprintf(_('**%s** has an account on %%%%site.name%%%%, a [micro-blogging](http://en.wikipedia.org/wiki/Micro-blogging) service ' .
'based on the Free Software [Laconica](http://laconi.ca/) tool. '),
$this->user->nickname, $this->user->nickname);
}
$this->elementStart('div', array('id' => 'anon_notice')); $this->elementStart('div', array('id' => 'anon_notice'));
$this->raw(common_markup_to_html($m)); $this->raw(common_markup_to_html($m));
$this->elementEnd('div'); $this->elementEnd('div');

BIN
apple-touch-icon.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.1 KiB

View File

@ -799,4 +799,98 @@ class Notice extends Memcached_DataObject
} }
} }
} }
function asAtomEntry($namespace=false, $source=false)
{
$profile = $this->getProfile();
$xs = new XMLStringer(true);
if ($namespace) {
$attrs = array('xmlns' => 'http://www.w3.org/2005/Atom',
'xmlns:thr' => 'http://purl.org/syndication/thread/1.0');
} else {
$attrs = array();
}
$xs->elementStart('entry', $attrs);
if ($source) {
$xs->elementStart('source');
$xs->element('title', null, $profile->nickname . " - " . common_config('site', 'name'));
$xs->element('link', array('href' => $profile->profileurl));
$user = User::staticGet('id', $profile->id);
if (!empty($user)) {
$atom_feed = common_local_url('api',
array('apiaction' => 'statuses',
'method' => 'user_timeline',
'argument' => $profile->nickname.'.atom'));
$xs->element('link', array('rel' => 'self',
'type' => 'application/atom+xml',
'href' => $profile->profileurl));
$xs->element('link', array('rel' => 'license',
'href' => common_config('license', 'url')));
}
$xs->element('icon', null, $profile->avatarUrl(AVATAR_PROFILE_SIZE));
}
$xs->elementStart('author');
$xs->element('name', null, $profile->nickname);
$xs->element('uri', null, $profile->profileurl);
$xs->elementEnd('author');
if ($source) {
$xs->elementEnd('source');
}
$xs->element('title', null, $this->content);
$xs->element('summary', null, $this->content);
$xs->element('link', array('rel' => 'alternate',
'href' => $this->bestUrl()));
$xs->element('id', null, $this->uri);
$xs->element('published', null, common_date_w3dtf($this->created));
$xs->element('updated', null, common_date_w3dtf($this->modified));
if ($this->reply_to) {
$reply_notice = Notice::staticGet('id', $this->reply_to);
if (!empty($reply_notice)) {
$xs->element('link', array('rel' => 'related',
'href' => $reply_notice->bestUrl()));
$xs->element('thr:in-reply-to',
array('ref' => $reply_notice->uri,
'href' => $reply_notice->bestUrl()));
}
}
$xs->element('content', array('type' => 'html'), $this->rendered);
$tag = new Notice_tag();
$tag->notice_id = $this->id;
if ($tag->find()) {
while ($tag->fetch()) {
$xs->element('category', array('term' => $tag->tag));
}
}
$tag->free();
$xs->elementEnd('entry');
return $xs->getString();
}
function bestUrl()
{
if (!empty($this->url)) {
return $this->url;
} else if (!empty($this->uri) && preg_match('/^https?:/', $this->uri)) {
return $this->uri;
} else {
return common_local_url('shownotice',
array('notice' => $this->id));
}
}
} }

View File

@ -1,7 +1,7 @@
<?php <?php
/* /*
* Laconica - a distributed open-source microblogging tool * Laconica - a distributed open-source microblogging tool
* Copyright (C) 2008, Controlez-Vous, Inc. * Copyright (C) 2008, 2009, Control Yourself, Inc.
* *
* This program is free software: you can redistribute it and/or modify * This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by * it under the terms of the GNU Affero General Public License as published by
@ -17,11 +17,14 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
if (!defined('LACONICA')) { exit(1); } if (!defined('LACONICA')) {
exit(1);
}
/** /**
* Table Definition for user * Table Definition for user
*/ */
require_once INSTALLDIR.'/classes/Memcached_DataObject.php'; require_once INSTALLDIR.'/classes/Memcached_DataObject.php';
require_once 'Validate.php'; require_once 'Validate.php';
@ -79,13 +82,13 @@ class User extends Memcached_DataObject
function isSubscribed($other) function isSubscribed($other)
{ {
assert(!is_null($other)); assert(!is_null($other));
# XXX: cache results of this query // XXX: cache results of this query
$sub = Subscription::pkeyGet(array('subscriber' => $this->id, $sub = Subscription::pkeyGet(array('subscriber' => $this->id,
'subscribed' => $other->id)); 'subscribed' => $other->id));
return (is_null($sub)) ? false : true; return (is_null($sub)) ? false : true;
} }
# 'update' won't write key columns, so we have to do it ourselves. // 'update' won't write key columns, so we have to do it ourselves.
function updateKeys(&$orig) function updateKeys(&$orig)
{ {
@ -96,7 +99,7 @@ class User extends Memcached_DataObject
} }
} }
if (count($parts) == 0) { if (count($parts) == 0) {
# No changes // No changes
return true; return true;
} }
$toupdate = implode(', ', $parts); $toupdate = implode(', ', $parts);
@ -117,7 +120,7 @@ class User extends Memcached_DataObject
function allowed_nickname($nickname) function allowed_nickname($nickname)
{ {
# XXX: should already be validated for size, content, etc. // XXX: should already be validated for size, content, etc.
static $blacklist = array('rss', 'xrds', 'doc', 'main', static $blacklist = array('rss', 'xrds', 'doc', 'main',
'settings', 'notice', 'user', 'settings', 'notice', 'user',
'search', 'avatar', 'tag', 'tags', 'search', 'avatar', 'tag', 'tags',
@ -147,7 +150,7 @@ class User extends Memcached_DataObject
$sub->subscriber = $this->id; $sub->subscriber = $this->id;
$sub->subscribed = $other->id; $sub->subscribed = $other->id;
$sub->created = common_sql_now(); # current time $sub->created = common_sql_now(); // current time
if (!$sub->insert()) { if (!$sub->insert()) {
return false; return false;
@ -173,7 +176,7 @@ class User extends Memcached_DataObject
static function register($fields) { static function register($fields) {
# MAGICALLY put fields into current scope // MAGICALLY put fields into current scope
extract($fields); extract($fields);
@ -211,11 +214,11 @@ class User extends Memcached_DataObject
$user->id = $id; $user->id = $id;
$user->nickname = $nickname; $user->nickname = $nickname;
if (!empty($password)) { # may not have a password for OpenID users if (!empty($password)) { // may not have a password for OpenID users
$user->password = common_munge_password($password, $id); $user->password = common_munge_password($password, $id);
} }
# Users who respond to invite email have proven their ownership of that address // Users who respond to invite email have proven their ownership of that address
if (!empty($code)) { if (!empty($code)) {
$invite = Invitation::staticGet($code); $invite = Invitation::staticGet($code);
@ -240,7 +243,7 @@ class User extends Memcached_DataObject
return false; return false;
} }
# Everyone is subscribed to themself // Everyone is subscribed to themself
$subscription = new Subscription(); $subscription = new Subscription();
$subscription->subscriber = $user->id; $subscription->subscriber = $user->id;
@ -324,7 +327,7 @@ class User extends Memcached_DataObject
return $user; return $user;
} }
# Things we do when the email changes // Things we do when the email changes
function emailChanged() function emailChanged()
{ {
@ -345,46 +348,46 @@ class User extends Memcached_DataObject
{ {
$cache = common_memcache(); $cache = common_memcache();
# XXX: Kind of a hack. // XXX: Kind of a hack.
if ($cache) { if ($cache) {
# This is the stream of favorite notices, in rev chron // This is the stream of favorite notices, in rev chron
# order. This forces it into cache. // order. This forces it into cache.
$faves = $this->favoriteNotices(0, NOTICE_CACHE_WINDOW); $faves = $this->favoriteNotices(0, NOTICE_CACHE_WINDOW);
$cnt = 0; $cnt = 0;
while ($faves->fetch()) { while ($faves->fetch()) {
if ($faves->id < $notice->id) { if ($faves->id < $notice->id) {
# If we passed it, it's not a fave // If we passed it, it's not a fave
return false; return false;
} else if ($faves->id == $notice->id) { } else if ($faves->id == $notice->id) {
# If it matches a cached notice, then it's a fave // If it matches a cached notice, then it's a fave
return true; return true;
} }
$cnt++; $cnt++;
} }
# If we're not past the end of the cache window, // If we're not past the end of the cache window,
# then the cache has all available faves, so this one // then the cache has all available faves, so this one
# is not a fave. // is not a fave.
if ($cnt < NOTICE_CACHE_WINDOW) { if ($cnt < NOTICE_CACHE_WINDOW) {
return false; return false;
} }
# Otherwise, cache doesn't have all faves; // Otherwise, cache doesn't have all faves;
# fall through to the default // fall through to the default
} }
$fave = Fave::pkeyGet(array('user_id' => $this->id, $fave = Fave::pkeyGet(array('user_id' => $this->id,
'notice_id' => $notice->id)); 'notice_id' => $notice->id));
return ((is_null($fave)) ? false : true); return ((is_null($fave)) ? false : true);
} }
function mutuallySubscribed($other) function mutuallySubscribed($other)
{ {
return $this->isSubscribed($other) && return $this->isSubscribed($other) &&
$other->isSubscribed($this); $other->isSubscribed($this);
} }
function mutuallySubscribedUsers() function mutuallySubscribedUsers()
{ {
// 3-way join; probably should get cached
# 3-way join; probably should get cached $UT = common_config('db','type')=='pgsql'?'"user"':'user';
$UT = common_config('db','type')=='pgsql'?'"user"':'user';
$qry = "SELECT $UT.* " . $qry = "SELECT $UT.* " .
"FROM subscription sub1 JOIN $UT ON sub1.subscribed = $UT.id " . "FROM subscription sub1 JOIN $UT ON sub1.subscribed = $UT.id " .
"JOIN subscription sub2 ON $UT.id = sub2.subscriber " . "JOIN subscription sub2 ON $UT.id = sub2.subscriber " .
@ -407,8 +410,8 @@ class User extends Memcached_DataObject
$offset, $limit, $since_id, $before_id, null, $since); $offset, $limit, $since_id, $before_id, null, $since);
} }
function getNotices($offset=0, $limit=NOTICES_PER_PAGE, $since_id=0, $before_id=0, $since=null) function getNotices($offset=0, $limit=NOTICES_PER_PAGE, $since_id=0, $before_id=0, $since=null)
{ {
$profile = $this->getProfile(); $profile = $this->getProfile();
if (!$profile) { if (!$profile) {
return null; return null;
@ -417,8 +420,8 @@ class User extends Memcached_DataObject
} }
} }
function favoriteNotices($offset=0, $limit=NOTICES_PER_PAGE) function favoriteNotices($offset=0, $limit=NOTICES_PER_PAGE)
{ {
$qry = $qry =
'SELECT notice.* ' . 'SELECT notice.* ' .
'FROM notice JOIN fave ON notice.id = fave.notice_id ' . 'FROM notice JOIN fave ON notice.id = fave.notice_id ' .
@ -428,12 +431,12 @@ class User extends Memcached_DataObject
$offset, $limit); $offset, $limit);
} }
function noticesWithFriends($offset=0, $limit=NOTICES_PER_PAGE, $since_id=0, $before_id=0, $since=null) function noticesWithFriends($offset=0, $limit=NOTICES_PER_PAGE, $since_id=0, $before_id=0, $since=null)
{ {
$enabled = common_config('inboxes', 'enabled'); $enabled = common_config('inboxes', 'enabled');
# Complicated code, depending on whether we support inboxes yet // Complicated code, depending on whether we support inboxes yet
# XXX: make this go away when inboxes become mandatory // XXX: make this go away when inboxes become mandatory
if ($enabled === false || if ($enabled === false ||
($enabled == 'transitional' && $this->inboxed == 0)) { ($enabled == 'transitional' && $this->inboxed == 0)) {
@ -443,13 +446,13 @@ class User extends Memcached_DataObject
'WHERE subscription.subscriber = %d '; 'WHERE subscription.subscriber = %d ';
$order = null; $order = null;
} else if ($enabled === true || } else if ($enabled === true ||
($enabled == 'transitional' && $this->inboxed == 1)) { ($enabled == 'transitional' && $this->inboxed == 1)) {
$qry = $qry =
'SELECT notice.* ' . 'SELECT notice.* ' .
'FROM notice JOIN notice_inbox ON notice.id = notice_inbox.notice_id ' . 'FROM notice JOIN notice_inbox ON notice.id = notice_inbox.notice_id ' .
'WHERE notice_inbox.user_id = %d '; 'WHERE notice_inbox.user_id = %d ';
# NOTE: we override ORDER // NOTE: we override ORDER
$order = null; $order = null;
} }
return Notice::getStream(sprintf($qry, $this->id), return Notice::getStream(sprintf($qry, $this->id),
@ -458,35 +461,34 @@ class User extends Memcached_DataObject
$order, $since); $order, $since);
} }
function blowFavesCache() function blowFavesCache()
{ {
$cache = common_memcache(); $cache = common_memcache();
if ($cache) { if ($cache) {
# Faves don't happen chronologically, so we need to blow // Faves don't happen chronologically, so we need to blow
# ;last cache, too // ;last cache, too
$cache->delete(common_cache_key('user:faves:'.$this->id)); $cache->delete(common_cache_key('user:faves:'.$this->id));
$cache->delete(common_cache_key('user:faves:'.$this->id).';last'); $cache->delete(common_cache_key('user:faves:'.$this->id).';last');
} }
} }
function getSelfTags() function getSelfTags()
{ {
return Profile_tag::getTags($this->id, $this->id); return Profile_tag::getTags($this->id, $this->id);
} }
function setSelfTags($newtags) function setSelfTags($newtags)
{ {
return Profile_tag::setTags($this->id, $this->id, $newtags); return Profile_tag::setTags($this->id, $this->id, $newtags);
} }
function block($other) function block($other)
{ {
// Add a new block record
# Add a new block record
$block = new Profile_block(); $block = new Profile_block();
# Begin a transaction // Begin a transaction
$block->query('BEGIN'); $block->query('BEGIN');
@ -500,7 +502,7 @@ class User extends Memcached_DataObject
return false; return false;
} }
# Cancel their subscription, if it exists // Cancel their subscription, if it exists
$sub = Subscription::pkeyGet(array('subscriber' => $other->id, $sub = Subscription::pkeyGet(array('subscriber' => $other->id,
'subscribed' => $this->id)); 'subscribed' => $this->id));
@ -520,8 +522,7 @@ class User extends Memcached_DataObject
function unblock($other) function unblock($other)
{ {
// Get the block record
# Get the block record
$block = Profile_block::get($this->id, $other->id); $block = Profile_block::get($this->id, $other->id);

View File

@ -13,7 +13,7 @@ create table profile (
index profile_nickname_idx (nickname), index profile_nickname_idx (nickname),
FULLTEXT(nickname, fullname, location, bio, homepage) FULLTEXT(nickname, fullname, location, bio, homepage)
) ENGINE=MyISAM CHARACTER SET utf8 COLLATE utf8_bin; ) ENGINE=MyISAM CHARACTER SET utf8 COLLATE utf8_general_ci;
create table avatar ( create table avatar (
profile_id integer not null comment 'foreign key to profile table' references profile (id), profile_id integer not null comment 'foreign key to profile table' references profile (id),
@ -73,7 +73,7 @@ create table user (
modified timestamp comment 'date this record was modified', modified timestamp comment 'date this record was modified',
index user_smsemail_idx (smsemail) index user_smsemail_idx (smsemail)
) ENGINE=InnoDB CHARACTER SET utf8 COLLATE utf8_bin; ) ENGINE=InnoDB CHARACTER SET utf8 COLLATE utf8_general_ci;
/* remote people */ /* remote people */
@ -103,7 +103,6 @@ create table subscription (
) ENGINE=InnoDB CHARACTER SET utf8 COLLATE utf8_bin; ) ENGINE=InnoDB CHARACTER SET utf8 COLLATE utf8_bin;
create table notice ( create table notice (
id integer auto_increment primary key comment 'unique identifier', id integer auto_increment primary key comment 'unique identifier',
profile_id integer not null comment 'who made the update' references profile (id), profile_id integer not null comment 'who made the update' references profile (id),
uri varchar(255) unique key comment 'universally unique identifier, usually a tag URI', uri varchar(255) unique key comment 'universally unique identifier, usually a tag URI',
@ -119,7 +118,7 @@ create table notice (
index notice_profile_id_idx (profile_id), index notice_profile_id_idx (profile_id),
index notice_created_idx (created), index notice_created_idx (created),
FULLTEXT(content) FULLTEXT(content)
) ENGINE=MyISAM CHARACTER SET utf8 COLLATE utf8_bin; ) ENGINE=MyISAM CHARACTER SET utf8 COLLATE utf8_general_ci;
create table notice_source ( create table notice_source (
code varchar(32) primary key not null comment 'source code', code varchar(32) primary key not null comment 'source code',
@ -130,7 +129,6 @@ create table notice_source (
) ENGINE=InnoDB CHARACTER SET utf8 COLLATE utf8_bin; ) ENGINE=InnoDB CHARACTER SET utf8 COLLATE utf8_bin;
create table reply ( create table reply (
notice_id integer not null comment 'notice that is the reply' references notice (id), notice_id integer not null comment 'notice that is the reply' references notice (id),
profile_id integer not null comment 'profile replied to' references profile (id), profile_id integer not null comment 'profile replied to' references profile (id),
modified timestamp not null comment 'date this record was modified', modified timestamp not null comment 'date this record was modified',
@ -144,7 +142,6 @@ create table reply (
) ENGINE=InnoDB CHARACTER SET utf8 COLLATE utf8_bin; ) ENGINE=InnoDB CHARACTER SET utf8 COLLATE utf8_bin;
create table fave ( create table fave (
notice_id integer not null comment 'notice that is the favorite' references notice (id), notice_id integer not null comment 'notice that is the favorite' references notice (id),
user_id integer not null comment 'user who likes this notice' references user (id), user_id integer not null comment 'user who likes this notice' references user (id),
modified timestamp not null comment 'date this record was modified', modified timestamp not null comment 'date this record was modified',
@ -321,7 +318,6 @@ create table invitation (
) ENGINE=InnoDB CHARACTER SET utf8 COLLATE utf8_bin; ) ENGINE=InnoDB CHARACTER SET utf8 COLLATE utf8_bin;
create table message ( create table message (
id integer auto_increment primary key comment 'unique identifier', id integer auto_increment primary key comment 'unique identifier',
uri varchar(255) unique key comment 'universally unique identifier', uri varchar(255) unique key comment 'universally unique identifier',
from_profile integer not null comment 'who the message is from' references profile (id), from_profile integer not null comment 'who the message is from' references profile (id),
@ -336,10 +332,9 @@ create table message (
index message_from_idx (from_profile), index message_from_idx (from_profile),
index message_to_idx (to_profile), index message_to_idx (to_profile),
index message_created_idx (created) index message_created_idx (created)
) ENGINE=InnoDB CHARACTER SET utf8 COLLATE utf8_bin; ) ENGINE=InnoDB CHARACTER SET utf8 COLLATE utf8_general_ci;
create table notice_inbox ( create table notice_inbox (
user_id integer not null comment 'user receiving the message' references user (id), user_id integer not null comment 'user receiving the message' references user (id),
notice_id integer not null comment 'notice received' references notice (id), notice_id integer not null comment 'notice received' references notice (id),
created datetime not null comment 'date the notice was created', created datetime not null comment 'date the notice was created',
@ -362,7 +357,6 @@ create table profile_tag (
) ENGINE=InnoDB CHARACTER SET utf8 COLLATE utf8_bin; ) ENGINE=InnoDB CHARACTER SET utf8 COLLATE utf8_bin;
create table profile_block ( create table profile_block (
blocker integer not null comment 'user making the block' references user (id), blocker integer not null comment 'user making the block' references user (id),
blocked integer not null comment 'profile that is blocked' references profile (id), blocked integer not null comment 'profile that is blocked' references profile (id),
modified timestamp comment 'date of blocking', modified timestamp comment 'date of blocking',
@ -372,7 +366,6 @@ create table profile_block (
) ENGINE=InnoDB CHARACTER SET utf8 COLLATE utf8_bin; ) ENGINE=InnoDB CHARACTER SET utf8 COLLATE utf8_bin;
create table user_group ( create table user_group (
id integer auto_increment primary key comment 'unique identifier', id integer auto_increment primary key comment 'unique identifier',
nickname varchar(64) unique key comment 'nickname for addressing', nickname varchar(64) unique key comment 'nickname for addressing',
@ -391,10 +384,9 @@ create table user_group (
index user_group_nickname_idx (nickname) index user_group_nickname_idx (nickname)
) ENGINE=InnoDB CHARACTER SET utf8 COLLATE utf8_bin; ) ENGINE=InnoDB CHARACTER SET utf8 COLLATE utf8_general_ci;
create table group_member ( create table group_member (
group_id integer not null comment 'foreign key to user_group' references user_group (id), group_id integer not null comment 'foreign key to user_group' references user_group (id),
profile_id integer not null comment 'foreign key to profile table' references profile (id), profile_id integer not null comment 'foreign key to profile table' references profile (id),
is_admin boolean default false comment 'is this user an admin?', is_admin boolean default false comment 'is this user an admin?',
@ -409,7 +401,6 @@ create table group_member (
) ENGINE=InnoDB CHARACTER SET utf8 COLLATE utf8_bin; ) ENGINE=InnoDB CHARACTER SET utf8 COLLATE utf8_bin;
create table related_group ( create table related_group (
group_id integer not null comment 'foreign key to user_group' references user_group (id), group_id integer not null comment 'foreign key to user_group' references user_group (id),
related_group_id integer not null comment 'foreign key to user_group' references user_group (id), related_group_id integer not null comment 'foreign key to user_group' references user_group (id),

View File

@ -19,6 +19,7 @@ VALUES
('identichat','identichat','http://identichat.prosody.im/', now()), ('identichat','identichat','http://identichat.prosody.im/', now()),
('identitwitch','IdentiTwitch','http://richfish.org/identitwitch/', now()), ('identitwitch','IdentiTwitch','http://richfish.org/identitwitch/', now()),
('mbpidgin','mbpidgin','http://code.google.com/p/microblog-purple/', now()), ('mbpidgin','mbpidgin','http://code.google.com/p/microblog-purple/', now()),
('Mobidentica', 'Mobidentica', 'http://www.substanceofcode.com/software/mobidentica/', now()),
('moconica','Moconica','http://moconica.com/', now()), ('moconica','Moconica','http://moconica.com/', now()),
('pocketwit','PockeTwit','http://code.google.com/p/pocketwit/', now()), ('pocketwit','PockeTwit','http://code.google.com/p/pocketwit/', now()),
('posty','Posty','http://spreadingfunkyness.com/posty/', now()), ('posty','Posty','http://spreadingfunkyness.com/posty/', now()),
@ -44,4 +45,4 @@ VALUES
('twitux','Twitux','http://live.gnome.org/DanielMorales/Twitux', now()), ('twitux','Twitux','http://live.gnome.org/DanielMorales/Twitux', now()),
('twitvim','TwitVim','http://vim.sourceforge.net/scripts/script.php?script_id=2204', now()), ('twitvim','TwitVim','http://vim.sourceforge.net/scripts/script.php?script_id=2204', now()),
('urfastr','urfastr','http://urfastr.net/', now()), ('urfastr','urfastr','http://urfastr.net/', now()),
('adium', 'Adium', 'http://www.adiumx.com/', now())); ('adium', 'Adium', 'http://www.adiumx.com/', now());

499
js/jquery.js vendored
View File

@ -1,13 +1,13 @@
/*! /*!
* jQuery JavaScript Library v1.3.1 * jQuery JavaScript Library v1.3.2
* http://jquery.com/ * http://jquery.com/
* *
* Copyright (c) 2009 John Resig * Copyright (c) 2009 John Resig
* Dual licensed under the MIT and GPL licenses. * Dual licensed under the MIT and GPL licenses.
* http://docs.jquery.com/License * http://docs.jquery.com/License
* *
* Date: 2009-01-21 20:42:16 -0500 (Wed, 21 Jan 2009) * Date: 2009-02-19 17:34:21 -0500 (Thu, 19 Feb 2009)
* Revision: 6158 * Revision: 6246
*/ */
(function(){ (function(){
@ -88,14 +88,16 @@ jQuery.fn = jQuery.prototype = {
this.context = selector.context; this.context = selector.context;
} }
return this.setArray(jQuery.makeArray(selector)); return this.setArray(jQuery.isArray( selector ) ?
selector :
jQuery.makeArray(selector));
}, },
// Start with an empty selector // Start with an empty selector
selector: "", selector: "",
// The current version of jQuery being used // The current version of jQuery being used
jquery: "1.3.1", jquery: "1.3.2",
// The number of elements contained in the matched element set // The number of elements contained in the matched element set
size: function() { size: function() {
@ -108,7 +110,7 @@ jQuery.fn = jQuery.prototype = {
return num === undefined ? return num === undefined ?
// Return a 'clean' array // Return a 'clean' array
jQuery.makeArray( this ) : Array.prototype.slice.call( this ) :
// Return just the object // Return just the object
this[ num ]; this[ num ];
@ -278,23 +280,21 @@ jQuery.fn = jQuery.prototype = {
}, },
// For internal use only. // For internal use only.
// Behaves like an Array's .push method, not like a jQuery method. // Behaves like an Array's method, not like a jQuery method.
push: [].push, push: [].push,
sort: [].sort,
splice: [].splice,
find: function( selector ) { find: function( selector ) {
if ( this.length === 1 && !/,/.test(selector) ) { if ( this.length === 1 ) {
var ret = this.pushStack( [], "find", selector ); var ret = this.pushStack( [], "find", selector );
ret.length = 0; ret.length = 0;
jQuery.find( selector, this[0], ret ); jQuery.find( selector, this[0], ret );
return ret; return ret;
} else { } else {
var elems = jQuery.map(this, function(elem){ return this.pushStack( jQuery.unique(jQuery.map(this, function(elem){
return jQuery.find( selector, elem ); return jQuery.find( selector, elem );
}); })), "find", selector );
return this.pushStack( /[^+>] [^+>]/.test( selector ) ?
jQuery.unique( elems ) :
elems, "find", selector );
} }
}, },
@ -310,33 +310,37 @@ jQuery.fn = jQuery.prototype = {
// attributes in IE that are actually only stored // attributes in IE that are actually only stored
// as properties will not be copied (such as the // as properties will not be copied (such as the
// the name attribute on an input). // the name attribute on an input).
var clone = this.cloneNode(true), var html = this.outerHTML;
container = document.createElement("div"); if ( !html ) {
container.appendChild(clone); var div = this.ownerDocument.createElement("div");
return jQuery.clean([container.innerHTML])[0]; div.appendChild( this.cloneNode(true) );
html = div.innerHTML;
}
return jQuery.clean([html.replace(/ jQuery\d+="(?:\d+|null)"/g, "").replace(/^\s*/, "")])[0];
} else } else
return this.cloneNode(true); return this.cloneNode(true);
}); });
// Need to set the expando to null on the cloned set if it exists
// removeData doesn't work here, IE removes it from the original as well
// this is primarily for IE but the data expando shouldn't be copied over in any browser
var clone = ret.find("*").andSelf().each(function(){
if ( this[ expando ] !== undefined )
this[ expando ] = null;
});
// Copy the events from the original to the clone // Copy the events from the original to the clone
if ( events === true ) if ( events === true ) {
this.find("*").andSelf().each(function(i){ var orig = this.find("*").andSelf(), i = 0;
if (this.nodeType == 3)
return;
var events = jQuery.data( this, "events" );
for ( var type in events ) ret.find("*").andSelf().each(function(){
for ( var handler in events[ type ] ) if ( this.nodeName !== orig[i].nodeName )
jQuery.event.add( clone[ i ], type, events[ type ][ handler ], events[ type ][ handler ].data ); return;
var events = jQuery.data( orig[i], "events" );
for ( var type in events ) {
for ( var handler in events[ type ] ) {
jQuery.event.add( this, type, events[ type ][ handler ], events[ type ][ handler ].data );
}
}
i++;
}); });
}
// Return the cloned set // Return the cloned set
return ret; return ret;
@ -355,14 +359,18 @@ jQuery.fn = jQuery.prototype = {
}, },
closest: function( selector ) { closest: function( selector ) {
var pos = jQuery.expr.match.POS.test( selector ) ? jQuery(selector) : null; var pos = jQuery.expr.match.POS.test( selector ) ? jQuery(selector) : null,
closer = 0;
return this.map(function(){ return this.map(function(){
var cur = this; var cur = this;
while ( cur && cur.ownerDocument ) { while ( cur && cur.ownerDocument ) {
if ( pos ? pos.index(cur) > -1 : jQuery(cur).is(selector) ) if ( pos ? pos.index(cur) > -1 : jQuery(cur).is(selector) ) {
jQuery.data(cur, "closest", closer);
return cur; return cur;
}
cur = cur.parentNode; cur = cur.parentNode;
closer++;
} }
}); });
}, },
@ -475,7 +483,7 @@ jQuery.fn = jQuery.prototype = {
html: function( value ) { html: function( value ) {
return value === undefined ? return value === undefined ?
(this[0] ? (this[0] ?
this[0].innerHTML : this[0].innerHTML.replace(/ jQuery\d+="(?:\d+|null)"/g, "") :
null) : null) :
this.empty().append( value ); this.empty().append( value );
}, },
@ -507,13 +515,13 @@ jQuery.fn = jQuery.prototype = {
if ( this[0] ) { if ( this[0] ) {
var fragment = (this[0].ownerDocument || this[0]).createDocumentFragment(), var fragment = (this[0].ownerDocument || this[0]).createDocumentFragment(),
scripts = jQuery.clean( args, (this[0].ownerDocument || this[0]), fragment ), scripts = jQuery.clean( args, (this[0].ownerDocument || this[0]), fragment ),
first = fragment.firstChild, first = fragment.firstChild;
extra = this.length > 1 ? fragment.cloneNode(true) : fragment;
if ( first ) if ( first )
for ( var i = 0, l = this.length; i < l; i++ ) for ( var i = 0, l = this.length; i < l; i++ )
callback.call( root(this[i], first), i > 0 ? extra.cloneNode(true) : fragment ); callback.call( root(this[i], first), this.length > 1 || i > 0 ?
fragment.cloneNode(true) : fragment );
if ( scripts ) if ( scripts )
jQuery.each( scripts, evalScript ); jQuery.each( scripts, evalScript );
} }
@ -636,9 +644,7 @@ jQuery.extend({
// Evalulates a script in a global context // Evalulates a script in a global context
globalEval: function( data ) { globalEval: function( data ) {
data = jQuery.trim( data ); if ( data && /\S/.test(data) ) {
if ( data ) {
// Inspired by code by Andrea Giammarchi // Inspired by code by Andrea Giammarchi
// http://webreflection.blogspot.com/2007/08/global-scope-evaluation-and-dom.html // http://webreflection.blogspot.com/2007/08/global-scope-evaluation-and-dom.html
var head = document.getElementsByTagName("head")[0] || document.documentElement, var head = document.getElementsByTagName("head")[0] || document.documentElement,
@ -741,26 +747,32 @@ jQuery.extend({
elem.style[ name ] = old[ name ]; elem.style[ name ] = old[ name ];
}, },
css: function( elem, name, force ) { css: function( elem, name, force, extra ) {
if ( name == "width" || name == "height" ) { if ( name == "width" || name == "height" ) {
var val, props = { position: "absolute", visibility: "hidden", display:"block" }, which = name == "width" ? [ "Left", "Right" ] : [ "Top", "Bottom" ]; var val, props = { position: "absolute", visibility: "hidden", display:"block" }, which = name == "width" ? [ "Left", "Right" ] : [ "Top", "Bottom" ];
function getWH() { function getWH() {
val = name == "width" ? elem.offsetWidth : elem.offsetHeight; val = name == "width" ? elem.offsetWidth : elem.offsetHeight;
var padding = 0, border = 0;
if ( extra === "border" )
return;
jQuery.each( which, function() { jQuery.each( which, function() {
padding += parseFloat(jQuery.curCSS( elem, "padding" + this, true)) || 0; if ( !extra )
border += parseFloat(jQuery.curCSS( elem, "border" + this + "Width", true)) || 0; val -= parseFloat(jQuery.curCSS( elem, "padding" + this, true)) || 0;
if ( extra === "margin" )
val += parseFloat(jQuery.curCSS( elem, "margin" + this, true)) || 0;
else
val -= parseFloat(jQuery.curCSS( elem, "border" + this + "Width", true)) || 0;
}); });
val -= Math.round(padding + border);
} }
if ( jQuery(elem).is(":visible") ) if ( elem.offsetWidth !== 0 )
getWH(); getWH();
else else
jQuery.swap( elem, props, getWH ); jQuery.swap( elem, props, getWH );
return Math.max(0, val); return Math.max(0, Math.round(val));
} }
return jQuery.curCSS( elem, name, force ); return jQuery.curCSS( elem, name, force );
@ -866,7 +878,7 @@ jQuery.extend({
}); });
// Trim whitespace, otherwise indexOf won't work as expected // Trim whitespace, otherwise indexOf won't work as expected
var tags = jQuery.trim( elem ).toLowerCase(); var tags = elem.replace(/^\s+/, "").substring(0, 10).toLowerCase();
var wrap = var wrap =
// option or optgroup // option or optgroup
@ -906,11 +918,12 @@ jQuery.extend({
if ( !jQuery.support.tbody ) { if ( !jQuery.support.tbody ) {
// String was a <table>, *may* have spurious <tbody> // String was a <table>, *may* have spurious <tbody>
var tbody = !tags.indexOf("<table") && tags.indexOf("<tbody") < 0 ? var hasBody = /<tbody/i.test(elem),
div.firstChild && div.firstChild.childNodes : tbody = !tags.indexOf("<table") && !hasBody ?
div.firstChild && div.firstChild.childNodes :
// String was a bare <thead> or <tfoot> // String was a bare <thead> or <tfoot>
wrap[1] == "<table>" && tags.indexOf("<tbody") < 0 ? wrap[1] == "<table>" && !hasBody ?
div.childNodes : div.childNodes :
[]; [];
@ -1189,13 +1202,16 @@ jQuery.each({
insertAfter: "after", insertAfter: "after",
replaceAll: "replaceWith" replaceAll: "replaceWith"
}, function(name, original){ }, function(name, original){
jQuery.fn[ name ] = function() { jQuery.fn[ name ] = function( selector ) {
var args = arguments; var ret = [], insert = jQuery( selector );
return this.each(function(){ for ( var i = 0, l = insert.length; i < l; i++ ) {
for ( var i = 0, length = args.length; i < length; i++ ) var elems = (i > 0 ? this.clone(true) : this).get();
jQuery( args[ i ] )[ original ]( this ); jQuery.fn[ original ].apply( jQuery(insert[i]), elems );
}); ret = ret.concat( elems );
}
return this.pushStack( ret, name, selector );
}; };
}); });
@ -1234,7 +1250,7 @@ jQuery.each({
empty: function() { empty: function() {
// Remove element nodes and prevent memory leaks // Remove element nodes and prevent memory leaks
jQuery( ">*", this ).remove(); jQuery(this).children().remove();
// Remove any remaining nodes // Remove any remaining nodes
while ( this.firstChild ) while ( this.firstChild )
@ -1402,7 +1418,7 @@ jQuery.fn.extend({
*/ */
(function(){ (function(){
var chunker = /((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^[\]]*\]|['"][^'"]+['"]|[^[\]'"]+)+\]|\\.|[^ >+~,(\[]+)+|[>+~])(\s*,\s*)?/g, var chunker = /((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^[\]]*\]|['"][^'"]*['"]|[^[\]'"]+)+\]|\\.|[^ >+~,(\[\\]+)+|[>+~])(\s*,\s*)?/g,
done = 0, done = 0,
toString = Object.prototype.toString; toString = Object.prototype.toString;
@ -1507,6 +1523,19 @@ var Sizzle = function(selector, context, results, seed) {
if ( extra ) { if ( extra ) {
Sizzle( extra, context, results, seed ); Sizzle( extra, context, results, seed );
if ( sortOrder ) {
hasDuplicate = false;
results.sort(sortOrder);
if ( hasDuplicate ) {
for ( var i = 1; i < results.length; i++ ) {
if ( results[i] === results[i-1] ) {
results.splice(i--, 1);
}
}
}
}
} }
return results; return results;
@ -1548,7 +1577,8 @@ Sizzle.find = function(expr, context, isXML){
}; };
Sizzle.filter = function(expr, set, inplace, not){ Sizzle.filter = function(expr, set, inplace, not){
var old = expr, result = [], curLoop = set, match, anyFound; var old = expr, result = [], curLoop = set, match, anyFound,
isXMLFilter = set && set[0] && isXML(set[0]);
while ( expr && set.length ) { while ( expr && set.length ) {
for ( var type in Expr.filter ) { for ( var type in Expr.filter ) {
@ -1561,7 +1591,7 @@ Sizzle.filter = function(expr, set, inplace, not){
} }
if ( Expr.preFilter[ type ] ) { if ( Expr.preFilter[ type ] ) {
match = Expr.preFilter[ type ]( match, curLoop, inplace, result, not ); match = Expr.preFilter[ type ]( match, curLoop, inplace, result, not, isXMLFilter );
if ( !match ) { if ( !match ) {
anyFound = found = true; anyFound = found = true;
@ -1606,8 +1636,6 @@ Sizzle.filter = function(expr, set, inplace, not){
} }
} }
expr = expr.replace(/\s*,\s*/, "");
// Improper expression // Improper expression
if ( expr == old ) { if ( expr == old ) {
if ( anyFound == null ) { if ( anyFound == null ) {
@ -1645,26 +1673,33 @@ var Expr = Sizzle.selectors = {
} }
}, },
relative: { relative: {
"+": function(checkSet, part){ "+": function(checkSet, part, isXML){
for ( var i = 0, l = checkSet.length; i < l; i++ ) { var isPartStr = typeof part === "string",
var elem = checkSet[i]; isTag = isPartStr && !/\W/.test(part),
if ( elem ) { isPartStrNotTag = isPartStr && !isTag;
var cur = elem.previousSibling;
while ( cur && cur.nodeType !== 1 ) { if ( isTag && !isXML ) {
cur = cur.previousSibling; part = part.toUpperCase();
} }
checkSet[i] = typeof part === "string" ?
cur || false : for ( var i = 0, l = checkSet.length, elem; i < l; i++ ) {
cur === part; if ( (elem = checkSet[i]) ) {
while ( (elem = elem.previousSibling) && elem.nodeType !== 1 ) {}
checkSet[i] = isPartStrNotTag || elem && elem.nodeName === part ?
elem || false :
elem === part;
} }
} }
if ( typeof part === "string" ) { if ( isPartStrNotTag ) {
Sizzle.filter( part, checkSet, true ); Sizzle.filter( part, checkSet, true );
} }
}, },
">": function(checkSet, part, isXML){ ">": function(checkSet, part, isXML){
if ( typeof part === "string" && !/\W/.test(part) ) { var isPartStr = typeof part === "string";
if ( isPartStr && !/\W/.test(part) ) {
part = isXML ? part : part.toUpperCase(); part = isXML ? part : part.toUpperCase();
for ( var i = 0, l = checkSet.length; i < l; i++ ) { for ( var i = 0, l = checkSet.length; i < l; i++ ) {
@ -1678,19 +1713,19 @@ var Expr = Sizzle.selectors = {
for ( var i = 0, l = checkSet.length; i < l; i++ ) { for ( var i = 0, l = checkSet.length; i < l; i++ ) {
var elem = checkSet[i]; var elem = checkSet[i];
if ( elem ) { if ( elem ) {
checkSet[i] = typeof part === "string" ? checkSet[i] = isPartStr ?
elem.parentNode : elem.parentNode :
elem.parentNode === part; elem.parentNode === part;
} }
} }
if ( typeof part === "string" ) { if ( isPartStr ) {
Sizzle.filter( part, checkSet, true ); Sizzle.filter( part, checkSet, true );
} }
} }
}, },
"": function(checkSet, part, isXML){ "": function(checkSet, part, isXML){
var doneName = "done" + (done++), checkFn = dirCheck; var doneName = done++, checkFn = dirCheck;
if ( !part.match(/\W/) ) { if ( !part.match(/\W/) ) {
var nodeCheck = part = isXML ? part : part.toUpperCase(); var nodeCheck = part = isXML ? part : part.toUpperCase();
@ -1700,7 +1735,7 @@ var Expr = Sizzle.selectors = {
checkFn("parentNode", part, doneName, checkSet, nodeCheck, isXML); checkFn("parentNode", part, doneName, checkSet, nodeCheck, isXML);
}, },
"~": function(checkSet, part, isXML){ "~": function(checkSet, part, isXML){
var doneName = "done" + (done++), checkFn = dirCheck; var doneName = done++, checkFn = dirCheck;
if ( typeof part === "string" && !part.match(/\W/) ) { if ( typeof part === "string" && !part.match(/\W/) ) {
var nodeCheck = part = isXML ? part : part.toUpperCase(); var nodeCheck = part = isXML ? part : part.toUpperCase();
@ -1718,8 +1753,16 @@ var Expr = Sizzle.selectors = {
} }
}, },
NAME: function(match, context, isXML){ NAME: function(match, context, isXML){
if ( typeof context.getElementsByName !== "undefined" && !isXML ) { if ( typeof context.getElementsByName !== "undefined" ) {
return context.getElementsByName(match[1]); var ret = [], results = context.getElementsByName(match[1]);
for ( var i = 0, l = results.length; i < l; i++ ) {
if ( results[i].getAttribute("name") === match[1] ) {
ret.push( results[i] );
}
}
return ret.length === 0 ? null : ret;
} }
}, },
TAG: function(match, context){ TAG: function(match, context){
@ -1727,13 +1770,16 @@ var Expr = Sizzle.selectors = {
} }
}, },
preFilter: { preFilter: {
CLASS: function(match, curLoop, inplace, result, not){ CLASS: function(match, curLoop, inplace, result, not, isXML){
match = " " + match[1].replace(/\\/g, "") + " "; match = " " + match[1].replace(/\\/g, "") + " ";
var elem; if ( isXML ) {
for ( var i = 0; (elem = curLoop[i]) != null; i++ ) { return match;
}
for ( var i = 0, elem; (elem = curLoop[i]) != null; i++ ) {
if ( elem ) { if ( elem ) {
if ( not ^ (" " + elem.className + " ").indexOf(match) >= 0 ) { if ( not ^ (elem.className && (" " + elem.className + " ").indexOf(match) >= 0) ) {
if ( !inplace ) if ( !inplace )
result.push( elem ); result.push( elem );
} else if ( inplace ) { } else if ( inplace ) {
@ -1764,14 +1810,14 @@ var Expr = Sizzle.selectors = {
} }
// TODO: Move to normal caching system // TODO: Move to normal caching system
match[0] = "done" + (done++); match[0] = done++;
return match; return match;
}, },
ATTR: function(match){ ATTR: function(match, curLoop, inplace, result, not, isXML){
var name = match[1].replace(/\\/g, ""); var name = match[1].replace(/\\/g, "");
if ( Expr.attrMap[name] ) { if ( !isXML && Expr.attrMap[name] ) {
match[1] = Expr.attrMap[name]; match[1] = Expr.attrMap[name];
} }
@ -1784,7 +1830,7 @@ var Expr = Sizzle.selectors = {
PSEUDO: function(match, curLoop, inplace, result, not){ PSEUDO: function(match, curLoop, inplace, result, not){
if ( match[1] === "not" ) { if ( match[1] === "not" ) {
// If we're dealing with a complex expression, or a simple one // If we're dealing with a complex expression, or a simple one
if ( match[3].match(chunker).length > 1 ) { if ( match[3].match(chunker).length > 1 || /^\w/.test(match[3]) ) {
match[3] = Sizzle(match[3], null, null, curLoop); match[3] = Sizzle(match[3], null, null, curLoop);
} else { } else {
var ret = Sizzle.filter(match[3], curLoop, inplace, true ^ not); var ret = Sizzle.filter(match[3], curLoop, inplace, true ^ not);
@ -1793,7 +1839,7 @@ var Expr = Sizzle.selectors = {
} }
return false; return false;
} }
} else if ( Expr.match.POS.test( match[0] ) ) { } else if ( Expr.match.POS.test( match[0] ) || Expr.match.CHILD.test( match[0] ) ) {
return true; return true;
} }
@ -1890,47 +1936,6 @@ var Expr = Sizzle.selectors = {
} }
}, },
filter: { filter: {
CHILD: function(elem, match){
var type = match[1], parent = elem.parentNode;
var doneName = match[0];
if ( parent && (!parent[ doneName ] || !elem.nodeIndex) ) {
var count = 1;
for ( var node = parent.firstChild; node; node = node.nextSibling ) {
if ( node.nodeType == 1 ) {
node.nodeIndex = count++;
}
}
parent[ doneName ] = count - 1;
}
if ( type == "first" ) {
return elem.nodeIndex == 1;
} else if ( type == "last" ) {
return elem.nodeIndex == parent[ doneName ];
} else if ( type == "only" ) {
return parent[ doneName ] == 1;
} else if ( type == "nth" ) {
var add = false, first = match[2], last = match[3];
if ( first == 1 && last == 0 ) {
return true;
}
if ( first == 0 ) {
if ( elem.nodeIndex == last ) {
add = true;
}
} else if ( (elem.nodeIndex - last) % first == 0 && (elem.nodeIndex - last) / first >= 0 ) {
add = true;
}
return add;
}
},
PSEUDO: function(elem, match, i, array){ PSEUDO: function(elem, match, i, array){
var name = match[1], filter = Expr.filters[ name ]; var name = match[1], filter = Expr.filters[ name ];
@ -1950,6 +1955,49 @@ var Expr = Sizzle.selectors = {
return true; return true;
} }
}, },
CHILD: function(elem, match){
var type = match[1], node = elem;
switch (type) {
case 'only':
case 'first':
while (node = node.previousSibling) {
if ( node.nodeType === 1 ) return false;
}
if ( type == 'first') return true;
node = elem;
case 'last':
while (node = node.nextSibling) {
if ( node.nodeType === 1 ) return false;
}
return true;
case 'nth':
var first = match[2], last = match[3];
if ( first == 1 && last == 0 ) {
return true;
}
var doneName = match[0],
parent = elem.parentNode;
if ( parent && (parent.sizcache !== doneName || !elem.nodeIndex) ) {
var count = 0;
for ( node = parent.firstChild; node; node = node.nextSibling ) {
if ( node.nodeType === 1 ) {
node.nodeIndex = ++count;
}
}
parent.sizcache = doneName;
}
var diff = elem.nodeIndex - last;
if ( first == 0 ) {
return diff == 0;
} else {
return ( diff % first == 0 && diff / first >= 0 );
}
}
},
ID: function(elem, match){ ID: function(elem, match){
return elem.nodeType === 1 && elem.getAttribute("id") === match; return elem.nodeType === 1 && elem.getAttribute("id") === match;
}, },
@ -1957,10 +2005,20 @@ var Expr = Sizzle.selectors = {
return (match === "*" && elem.nodeType === 1) || elem.nodeName === match; return (match === "*" && elem.nodeType === 1) || elem.nodeName === match;
}, },
CLASS: function(elem, match){ CLASS: function(elem, match){
return match.test( elem.className ); return (" " + (elem.className || elem.getAttribute("class")) + " ")
.indexOf( match ) > -1;
}, },
ATTR: function(elem, match){ ATTR: function(elem, match){
var result = Expr.attrHandle[ match[1] ] ? Expr.attrHandle[ match[1] ]( elem ) : elem[ match[1] ] || elem.getAttribute( match[1] ), value = result + "", type = match[2], check = match[4]; var name = match[1],
result = Expr.attrHandle[ name ] ?
Expr.attrHandle[ name ]( elem ) :
elem[ name ] != null ?
elem[ name ] :
elem.getAttribute( name ),
value = result + "",
type = match[2],
check = match[4];
return result == null ? return result == null ?
type === "!=" : type === "!=" :
type === "=" ? type === "=" ?
@ -1969,8 +2027,8 @@ var Expr = Sizzle.selectors = {
value.indexOf(check) >= 0 : value.indexOf(check) >= 0 :
type === "~=" ? type === "~=" ?
(" " + value + " ").indexOf(check) >= 0 : (" " + value + " ").indexOf(check) >= 0 :
!match[4] ? !check ?
result : value && result !== false :
type === "!=" ? type === "!=" ?
value != check : value != check :
type === "^=" ? type === "^=" ?
@ -2036,6 +2094,39 @@ try {
}; };
} }
var sortOrder;
if ( document.documentElement.compareDocumentPosition ) {
sortOrder = function( a, b ) {
var ret = a.compareDocumentPosition(b) & 4 ? -1 : a === b ? 0 : 1;
if ( ret === 0 ) {
hasDuplicate = true;
}
return ret;
};
} else if ( "sourceIndex" in document.documentElement ) {
sortOrder = function( a, b ) {
var ret = a.sourceIndex - b.sourceIndex;
if ( ret === 0 ) {
hasDuplicate = true;
}
return ret;
};
} else if ( document.createRange ) {
sortOrder = function( a, b ) {
var aRange = a.ownerDocument.createRange(), bRange = b.ownerDocument.createRange();
aRange.selectNode(a);
aRange.collapse(true);
bRange.selectNode(b);
bRange.collapse(true);
var ret = aRange.compareBoundaryPoints(Range.START_TO_END, bRange);
if ( ret === 0 ) {
hasDuplicate = true;
}
return ret;
};
}
// Check to see if the browser returns elements by name when // Check to see if the browser returns elements by name when
// querying by getElementById (and provide a workaround) // querying by getElementById (and provide a workaround)
(function(){ (function(){
@ -2099,7 +2190,8 @@ try {
// Check to see if an attribute returns normalized href attributes // Check to see if an attribute returns normalized href attributes
div.innerHTML = "<a href='#'></a>"; div.innerHTML = "<a href='#'></a>";
if ( div.firstChild && div.firstChild.getAttribute("href") !== "#" ) { if ( div.firstChild && typeof div.firstChild.getAttribute !== "undefined" &&
div.firstChild.getAttribute("href") !== "#" ) {
Expr.attrHandle.href = function(elem){ Expr.attrHandle.href = function(elem){
return elem.getAttribute("href", 2); return elem.getAttribute("href", 2);
}; };
@ -2136,29 +2228,50 @@ if ( document.querySelectorAll ) (function(){
Sizzle.matches = oldSizzle.matches; Sizzle.matches = oldSizzle.matches;
})(); })();
if ( document.getElementsByClassName && document.documentElement.getElementsByClassName ) { if ( document.getElementsByClassName && document.documentElement.getElementsByClassName ) (function(){
var div = document.createElement("div");
div.innerHTML = "<div class='test e'></div><div class='test'></div>";
// Opera can't find a second classname (in 9.6)
if ( div.getElementsByClassName("e").length === 0 )
return;
// Safari caches class attributes, doesn't catch changes (in 3.2)
div.lastChild.className = "e";
if ( div.getElementsByClassName("e").length === 1 )
return;
Expr.order.splice(1, 0, "CLASS"); Expr.order.splice(1, 0, "CLASS");
Expr.find.CLASS = function(match, context) { Expr.find.CLASS = function(match, context, isXML) {
return context.getElementsByClassName(match[1]); if ( typeof context.getElementsByClassName !== "undefined" && !isXML ) {
return context.getElementsByClassName(match[1]);
}
}; };
} })();
function dirNodeCheck( dir, cur, doneName, checkSet, nodeCheck, isXML ) { function dirNodeCheck( dir, cur, doneName, checkSet, nodeCheck, isXML ) {
var sibDir = dir == "previousSibling" && !isXML;
for ( var i = 0, l = checkSet.length; i < l; i++ ) { for ( var i = 0, l = checkSet.length; i < l; i++ ) {
var elem = checkSet[i]; var elem = checkSet[i];
if ( elem ) { if ( elem ) {
if ( sibDir && elem.nodeType === 1 ){
elem.sizcache = doneName;
elem.sizset = i;
}
elem = elem[dir]; elem = elem[dir];
var match = false; var match = false;
while ( elem && elem.nodeType ) { while ( elem ) {
var done = elem[doneName]; if ( elem.sizcache === doneName ) {
if ( done ) { match = checkSet[elem.sizset];
match = checkSet[ done ];
break; break;
} }
if ( elem.nodeType === 1 && !isXML ) if ( elem.nodeType === 1 && !isXML ){
elem[doneName] = i; elem.sizcache = doneName;
elem.sizset = i;
}
if ( elem.nodeName === cur ) { if ( elem.nodeName === cur ) {
match = elem; match = elem;
@ -2174,22 +2287,28 @@ function dirNodeCheck( dir, cur, doneName, checkSet, nodeCheck, isXML ) {
} }
function dirCheck( dir, cur, doneName, checkSet, nodeCheck, isXML ) { function dirCheck( dir, cur, doneName, checkSet, nodeCheck, isXML ) {
var sibDir = dir == "previousSibling" && !isXML;
for ( var i = 0, l = checkSet.length; i < l; i++ ) { for ( var i = 0, l = checkSet.length; i < l; i++ ) {
var elem = checkSet[i]; var elem = checkSet[i];
if ( elem ) { if ( elem ) {
if ( sibDir && elem.nodeType === 1 ) {
elem.sizcache = doneName;
elem.sizset = i;
}
elem = elem[dir]; elem = elem[dir];
var match = false; var match = false;
while ( elem && elem.nodeType ) { while ( elem ) {
if ( elem[doneName] ) { if ( elem.sizcache === doneName ) {
match = checkSet[ elem[doneName] ]; match = checkSet[elem.sizset];
break; break;
} }
if ( elem.nodeType === 1 ) { if ( elem.nodeType === 1 ) {
if ( !isXML ) if ( !isXML ) {
elem[doneName] = i; elem.sizcache = doneName;
elem.sizset = i;
}
if ( typeof cur !== "string" ) { if ( typeof cur !== "string" ) {
if ( elem === cur ) { if ( elem === cur ) {
match = true; match = true;
@ -2248,15 +2367,11 @@ jQuery.expr = Sizzle.selectors;
jQuery.expr[":"] = jQuery.expr.filters; jQuery.expr[":"] = jQuery.expr.filters;
Sizzle.selectors.filters.hidden = function(elem){ Sizzle.selectors.filters.hidden = function(elem){
return "hidden" === elem.type || return elem.offsetWidth === 0 || elem.offsetHeight === 0;
jQuery.css(elem, "display") === "none" ||
jQuery.css(elem, "visibility") === "hidden";
}; };
Sizzle.selectors.filters.visible = function(elem){ Sizzle.selectors.filters.visible = function(elem){
return "hidden" !== elem.type && return elem.offsetWidth > 0 || elem.offsetHeight > 0;
jQuery.css(elem, "display") !== "none" &&
jQuery.css(elem, "visibility") !== "hidden";
}; };
Sizzle.selectors.filters.animated = function(elem){ Sizzle.selectors.filters.animated = function(elem){
@ -2552,7 +2667,8 @@ jQuery.event = {
var all, handlers; var all, handlers;
event = arguments[0] = jQuery.event.fix( event || window.event ); event = arguments[0] = jQuery.event.fix( event || window.event );
event.currentTarget = this;
// Namespaced event handlers // Namespaced event handlers
var namespaces = event.type.split("."); var namespaces = event.type.split(".");
event.type = namespaces.shift(); event.type = namespaces.shift();
@ -2883,9 +2999,13 @@ function liveHandler( event ){
} }
}); });
elems.sort(function(a,b) {
return jQuery.data(a.elem, "closest") - jQuery.data(b.elem, "closest");
});
jQuery.each(elems, function(){ jQuery.each(elems, function(){
if ( this.fn.call(this.elem, event, this.fn.data) === false ) if ( this.fn.call(this.elem, event, this.fn.data) === false )
stop = false; return (stop = false);
}); });
return stop; return stop;
@ -2949,7 +3069,7 @@ function bindReady(){
// If IE and not an iframe // If IE and not an iframe
// continually check to see if the document is ready // continually check to see if the document is ready
if ( document.documentElement.doScroll && typeof window.frameElement === "undefined" ) (function(){ if ( document.documentElement.doScroll && window == window.top ) (function(){
if ( jQuery.isReady ) return; if ( jQuery.isReady ) return;
try { try {
@ -3079,12 +3199,11 @@ jQuery( window ).bind( 'unload', function(){
// document.body must exist before we can do this // document.body must exist before we can do this
jQuery(function(){ jQuery(function(){
var div = document.createElement("div"); var div = document.createElement("div");
div.style.width = "1px"; div.style.width = div.style.paddingLeft = "1px";
div.style.paddingLeft = "1px";
document.body.appendChild( div ); document.body.appendChild( div );
jQuery.boxModel = jQuery.support.boxModel = div.offsetWidth === 2; jQuery.boxModel = jQuery.support.boxModel = div.offsetWidth === 2;
document.body.removeChild( div ); document.body.removeChild( div ).style.display = 'none';
}); });
})(); })();
@ -3175,7 +3294,7 @@ jQuery.fn.extend({
.filter(function(){ .filter(function(){
return this.name && !this.disabled && return this.name && !this.disabled &&
(this.checked || /select|textarea/i.test(this.nodeName) || (this.checked || /select|textarea/i.test(this.nodeName) ||
/text|hidden|password/i.test(this.type)); /text|hidden|password|search/i.test(this.type));
}) })
.map(function(i, elem){ .map(function(i, elem){
var val = jQuery(this).val(); var val = jQuery(this).val();
@ -3371,6 +3490,9 @@ jQuery.extend({
done = true; done = true;
success(); success();
complete(); complete();
// Handle memory leak in IE
script.onload = script.onreadystatechange = null;
head.removeChild( script ); head.removeChild( script );
} }
}; };
@ -3686,9 +3808,15 @@ jQuery.fn.extend({
elemdisplay[ tagName ] = display; elemdisplay[ tagName ] = display;
} }
this[i].style.display = jQuery.data(this[i], "olddisplay", display); jQuery.data(this[i], "olddisplay", display);
} }
} }
// Set the display of the elements in a second loop
// to avoid the constant reflow
for ( var i = 0, l = this.length; i < l; i++ ){
this[i].style.display = jQuery.data(this[i], "olddisplay") || "";
}
return this; return this;
} }
@ -3702,8 +3830,14 @@ jQuery.fn.extend({
var old = jQuery.data(this[i], "olddisplay"); var old = jQuery.data(this[i], "olddisplay");
if ( !old && old !== "none" ) if ( !old && old !== "none" )
jQuery.data(this[i], "olddisplay", jQuery.css(this[i], "display")); jQuery.data(this[i], "olddisplay", jQuery.css(this[i], "display"));
}
// Set the display of the elements in a second loop
// to avoid the constant reflow
for ( var i = 0, l = this.length; i < l; i++ ){
this[i].style.display = "none"; this[i].style.display = "none";
} }
return this; return this;
} }
}, },
@ -3915,7 +4049,7 @@ jQuery.fx.prototype = {
t.elem = this.elem; t.elem = this.elem;
if ( t() && jQuery.timers.push(t) == 1 ) { if ( t() && jQuery.timers.push(t) && !timerId ) {
timerId = setInterval(function(){ timerId = setInterval(function(){
var timers = jQuery.timers; var timers = jQuery.timers;
@ -3925,6 +4059,7 @@ jQuery.fx.prototype = {
if ( !timers.length ) { if ( !timers.length ) {
clearInterval( timerId ); clearInterval( timerId );
timerId = undefined;
} }
}, 13); }, 13);
} }
@ -4193,22 +4328,21 @@ jQuery.each( ['Left', 'Top'], function(i, name) {
jQuery.each([ "Height", "Width" ], function(i, name){ jQuery.each([ "Height", "Width" ], function(i, name){
var tl = i ? "Left" : "Top", // top or left var tl = i ? "Left" : "Top", // top or left
br = i ? "Right" : "Bottom"; // bottom or right br = i ? "Right" : "Bottom", // bottom or right
lower = name.toLowerCase();
// innerHeight and innerWidth // innerHeight and innerWidth
jQuery.fn["inner" + name] = function(){ jQuery.fn["inner" + name] = function(){
return this[ name.toLowerCase() ]() + return this[0] ?
num(this, "padding" + tl) + jQuery.css( this[0], lower, false, "padding" ) :
num(this, "padding" + br); null;
}; };
// outerHeight and outerWidth // outerHeight and outerWidth
jQuery.fn["outer" + name] = function(margin) { jQuery.fn["outer" + name] = function(margin) {
return this["inner" + name]() + return this[0] ?
num(this, "border" + tl + "Width") + jQuery.css( this[0], lower, false, margin ? "margin" : "border" ) :
num(this, "border" + br + "Width") + null;
(margin ?
num(this, "margin" + tl) + num(this, "margin" + br) : 0);
}; };
var type = name.toLowerCase(); var type = name.toLowerCase();
@ -4238,4 +4372,5 @@ jQuery.each([ "Height", "Width" ], function(i, name){
this.css( type, typeof size === "string" ? size : size + "px" ); this.css( type, typeof size === "string" ? size : size + "px" );
}; };
});})(); });
})();

10
js/jquery.min.js vendored

File diff suppressed because one or more lines are too long

View File

@ -161,6 +161,7 @@ $(document).ready(function(){
$("#form_notice").addClass("warning"); $("#form_notice").addClass("warning");
return false; return false;
} }
$("#form_notice").addClass("processing");
$("#notice_action-submit").attr("disabled", "disabled"); $("#notice_action-submit").attr("disabled", "disabled");
$("#notice_action-submit").addClass("disabled"); $("#notice_action-submit").addClass("disabled");
return true; return true;
@ -179,6 +180,7 @@ $(document).ready(function(){
NoticeHover(); NoticeHover();
NoticeReply(); NoticeReply();
} }
$("#form_notice").removeClass("processing");
$("#notice_action-submit").removeAttr("disabled"); $("#notice_action-submit").removeAttr("disabled");
$("#notice_action-submit").removeClass("disabled"); $("#notice_action-submit").removeClass("disabled");
} }

View File

@ -112,6 +112,7 @@ class Action extends HTMLOutputter // lawsuit
// XXX: attributes (profile?) // XXX: attributes (profile?)
$this->elementStart('head'); $this->elementStart('head');
$this->showTitle(); $this->showTitle();
$this->showShortcutIcon();
$this->showStylesheets(); $this->showStylesheets();
$this->showScripts(); $this->showScripts();
$this->showOpenSearch(); $this->showOpenSearch();
@ -147,6 +148,32 @@ class Action extends HTMLOutputter // lawsuit
return _("Untitled page"); return _("Untitled page");
} }
/**
* Show themed shortcut icon
*
* @return nothing
*/
function showShortcutIcon()
{
if (is_readable(INSTALLDIR . '/theme/' . common_config('site', 'theme') . '/favicon.ico')) {
$this->element('link', array('rel' => 'shortcut icon',
'href' => theme_path('favicon.ico')));
} else {
$this->element('link', array('rel' => 'shortcut icon',
'href' => common_path('favicon.ico')));
}
if (common_config('site', 'mobile')) {
if (is_readable(INSTALLDIR . '/theme/' . common_config('site', 'theme') . '/apple-touch-icon.png')) {
$this->element('link', array('rel' => 'apple-touch-icon',
'href' => theme_path('apple-touch-icon.png')));
} else {
$this->element('link', array('rel' => 'apple-touch-icon',
'href' => common_path('apple-touch-icon.png')));
}
}
}
/** /**
* Show stylesheets * Show stylesheets
* *

View File

@ -163,50 +163,25 @@ function jabber_send_notice($to, $notice)
function jabber_format_entry($profile, $notice) function jabber_format_entry($profile, $notice)
{ {
// FIXME: notice url might be remote $entry = $notice->asAtomEntry(true, true);
$noticeurl = common_local_url('shownotice', $xs = new XMLStringer();
array('notice' => $notice->id)); $xs->elementStart('html', array('xmlns' => 'http://jabber.org/protocol/xhtml-im'));
$xs->elementStart('body', array('xmlns' => 'http://www.w3.org/1999/xhtml'));
$msg = jabber_format_notice($profile, $notice); $xs->element('a', array('href' => $profile->profileurl),
$profile->nickname);
$self_url = common_local_url('userrss', array('nickname' => $profile->nickname)); $xs->text(": ");
if (!empty($notice->rendered)) {
$entry = "\n<entry xmlns='http://www.w3.org/2005/Atom'>\n"; $xs->raw($notice->rendered);
$entry .= "<source>\n"; } else {
$entry .= "<title>" . $profile->nickname . " - " . common_config('site', 'name') . "</title>\n"; $xs->raw(common_render_content($notice->content, $notice));
$entry .= "<link href='" . htmlspecialchars($profile->profileurl) . "'/>\n";
$entry .= "<link rel='self' type='application/rss+xml' href='" . $self_url . "'/>\n";
$entry .= "<author><name>" . $profile->nickname . "</name></author>\n";
$entry .= "<icon>" . $profile->avatarUrl(AVATAR_PROFILE_SIZE) . "</icon>\n";
$entry .= "</source>\n";
$entry .= "<title>" . htmlspecialchars($msg) . "</title>\n";
$entry .= "<summary>" . htmlspecialchars($msg) . "</summary>\n";
$entry .= "<link rel='alternate' href='" . $noticeurl . "' />\n";
$entry .= "<id>". $notice->uri . "</id>\n";
$entry .= "<published>".common_date_w3dtf($notice->created)."</published>\n";
$entry .= "<updated>".common_date_w3dtf($notice->modified)."</updated>\n";
if ($notice->reply_to) {
$replyurl = common_local_url('shownotice',
array('notice' => $notice->reply_to));
$entry .= "<link rel='related' href='" . $replyurl . "'/>\n";
} }
$entry .= "</entry>\n"; $xs->elementEnd('body');
$xs->elementEnd('html');
$html = "\n<html xmlns='http://jabber.org/protocol/xhtml-im'>\n"; $html = $xs->getString();
$html .= "<body xmlns='http://www.w3.org/1999/xhtml'>\n";
$html .= "<a href='".htmlspecialchars($profile->profileurl)."'>".$profile->nickname."</a>: ";
$html .= ($notice->rendered) ? $notice->rendered : common_render_content($notice->content, $notice);
$html .= "\n</body>\n";
$html .= "\n</html>\n";
$address = "<addresses xmlns='http://jabber.org/protocol/address'>\n"; return $html . ' ' . $entry;
$address .= "<address type='replyto' jid='" . jabber_daemon_address() . "' />\n";
$address .= "</addresses>\n";
// FIXME: include a pubsub event, too.
return $html . $entry . $address;
} }
/** /**

View File

@ -115,7 +115,7 @@ function get_all_languages() {
'he' => array('q' => 0.5, 'lang' => 'he_IL', 'name' => 'Hebrew', 'direction' => 'rtl'), 'he' => array('q' => 0.5, 'lang' => 'he_IL', 'name' => 'Hebrew', 'direction' => 'rtl'),
'it' => array('q' => 1, 'lang' => 'it_IT', 'name' => 'Italian', 'direction' => 'ltr'), 'it' => array('q' => 1, 'lang' => 'it_IT', 'name' => 'Italian', 'direction' => 'ltr'),
'jp' => array('q' => 0.5, 'lang' => 'ja_JP', 'name' => 'Japanese', 'direction' => 'ltr'), 'jp' => array('q' => 0.5, 'lang' => 'ja_JP', 'name' => 'Japanese', 'direction' => 'ltr'),
'ko' => array('q' => 0.9, 'lang' => 'ko', 'name' => 'Korean', 'direction' => 'ltr'), 'ko' => array('q' => 0.9, 'lang' => 'ko_KR', 'name' => 'Korean', 'direction' => 'ltr'),
'mk' => array('q' => 0.5, 'lang' => 'mk_MK', 'name' => 'Macedonian', 'direction' => 'ltr'), 'mk' => array('q' => 0.5, 'lang' => 'mk_MK', 'name' => 'Macedonian', 'direction' => 'ltr'),
'nb' => array('q' => 0.1, 'lang' => 'nb_NO', 'name' => 'Norwegian (Bokmål)', 'direction' => 'ltr'), 'nb' => array('q' => 0.1, 'lang' => 'nb_NO', 'name' => 'Norwegian (Bokmål)', 'direction' => 'ltr'),
'no' => array('q' => 0.1, 'lang' => 'nb_NO', 'name' => 'Norwegian (Bokmål)', 'direction' => 'ltr'), 'no' => array('q' => 0.1, 'lang' => 'nb_NO', 'name' => 'Norwegian (Bokmål)', 'direction' => 'ltr'),

View File

@ -70,16 +70,16 @@ class LoginGroupNav extends Widget
function show() function show()
{ {
// action => array('prompt', 'title') // action => array('prompt', 'title')
$menu = $menu = array();
array('login' =>
array(_('Login'), $menu['login'] = array(_('Login'),
_('Login with a username and password')), _('Login with a username and password'));
'register' => if (!(common_config('site','closed') || common_config('site','inviteonly'))) {
array(_('Register'), $menu['register'] = array(_('Register'),
_('Sign up for a new account')), _('Sign up for a new account'));
'openidlogin' => }
array(_('OpenID'), $menu['openidlogin'] = array(_('OpenID'),
_('Login or register with OpenID'))); _('Login or register with OpenID'));
$action_name = $this->action->trimmed('action'); $action_name = $this->action->trimmed('action');
$this->action->elementStart('ul', array('class' => 'nav')); $this->action->elementStart('ul', array('class' => 'nav'));

View File

@ -132,20 +132,14 @@ class MessageForm extends Form
$mutual_users->free(); $mutual_users->free();
unset($mutual_users); unset($mutual_users);
$this->out->elementStart('ul', 'form_data');
$this->out->elementStart('li', array('id' => 'notice_to'));
$this->out->dropdown('to', _('To'), $mutual, null, false, $this->out->dropdown('to', _('To'), $mutual, null, false,
($this->to) ? $this->to->id : null); ($this->to) ? $this->to->id : null);
$this->out->elementEnd('li');
$this->out->elementStart('li', array('id' => 'notice_text'));
$this->out->element('textarea', array('id' => 'notice_data-text', $this->out->element('textarea', array('id' => 'notice_data-text',
'cols' => 35, 'cols' => 35,
'rows' => 4, 'rows' => 4,
'name' => 'content'), 'name' => 'content'),
($this->content) ? $this->content : ''); ($this->content) ? $this->content : '');
$this->out->elementEnd('li');
$this->out->elementEnd('ul');
} }
/** /**
@ -156,14 +150,10 @@ class MessageForm extends Form
function formActions() function formActions()
{ {
$this->out->elementStart('ul', 'form_actions');
$this->out->elementStart('li', array('id' => 'notice_submit'));
$this->out->element('input', array('id' => 'notice_action-submit', $this->out->element('input', array('id' => 'notice_action-submit',
'class' => 'submit', 'class' => 'submit',
'name' => 'message_send', 'name' => 'message_send',
'type' => 'submit', 'type' => 'submit',
'value' => _('Send'))); 'value' => _('Send')));
$this->out->elementEnd('li');
$this->out->elementEnd('ul');
} }
} }

View File

@ -134,9 +134,6 @@ class NoticeForm extends Form
function formData() function formData()
{ {
$this->out->elementStart('ul', 'form_data');
$this->out->elementStart('li', array('id' => 'notice_text'));
$this->out->element('label', array('for' => 'notice_data-text'), $this->out->element('label', array('for' => 'notice_data-text'),
sprintf(_('What\'s up, %s?'), $this->user->nickname)); sprintf(_('What\'s up, %s?'), $this->user->nickname));
// XXX: vary by defined max size // XXX: vary by defined max size
@ -145,8 +142,6 @@ class NoticeForm extends Form
'rows' => 4, 'rows' => 4,
'name' => 'status_textarea'), 'name' => 'status_textarea'),
($this->content) ? $this->content : ''); ($this->content) ? $this->content : '');
$this->out->elementEnd('li');
$this->out->elementEnd('ul');
$this->out->elementStart('dl', 'form_note'); $this->out->elementStart('dl', 'form_note');
$this->out->element('dt', null, _('Available characters')); $this->out->element('dt', null, _('Available characters'));
@ -168,14 +163,10 @@ class NoticeForm extends Form
function formActions() function formActions()
{ {
$this->out->elementStart('ul', 'form_actions');
$this->out->elementStart('li', array('id' => 'notice_submit'));
$this->out->element('input', array('id' => 'notice_action-submit', $this->out->element('input', array('id' => 'notice_action-submit',
'class' => 'submit', 'class' => 'submit',
'name' => 'status_submit', 'name' => 'status_submit',
'type' => 'submit', 'type' => 'submit',
'value' => _('Send'))); 'value' => _('Send')));
$this->out->elementEnd('li');
$this->out->elementEnd('ul');
} }
} }

View File

@ -68,8 +68,8 @@ class Router
} }
} }
function initialize() { function initialize()
{
$m = Net_URL_Mapper::getInstance(); $m = Net_URL_Mapper::getInstance();
// In the "root" // In the "root"
@ -136,14 +136,17 @@ class Router
foreach (array('group', 'people', 'notice') as $s) { foreach (array('group', 'people', 'notice') as $s) {
$m->connect('search/'.$s, array('action' => $s.'search')); $m->connect('search/'.$s, array('action' => $s.'search'));
$m->connect('search/'.$s.'?q=:q', array('action' => $s.'search'),array('q' => '.+')); $m->connect('search/'.$s.'?q=:q',
array('action' => $s.'search'),
array('q' => '.+'));
} }
// The second of these is needed to make the link work correctly // The second of these is needed to make the link work correctly
// when inserted into the page. The first is needed to match the // when inserted into the page. The first is needed to match the
// route on the way in. Seems to be another Net_URL_Mapper bug to me. // route on the way in. Seems to be another Net_URL_Mapper bug to me.
$m->connect('search/notice/rss', array('action' => 'noticesearchrss')); $m->connect('search/notice/rss', array('action' => 'noticesearchrss'));
$m->connect('search/notice/rss?q=:q', array('action' => 'noticesearchrss'),array('q' => '.+')); $m->connect('search/notice/rss?q=:q', array('action' => 'noticesearchrss'),
array('q' => '.+'));
// notice // notice
@ -263,8 +266,8 @@ class Router
foreach (array('xml', 'json', 'rss', 'atom') as $e) { foreach (array('xml', 'json', 'rss', 'atom') as $e) {
$m->connect('api/direct_messages/sent.'.$e, $m->connect('api/direct_messages/sent.'.$e,
array('action' => 'api', array('action' => 'api',
'apiaction' => 'direct_messages', 'apiaction' => 'direct_messages',
'method' => 'sent.'.$e)); 'method' => 'sent.'.$e));
} }
$m->connect('api/direct_messages/destroy/:argument', $m->connect('api/direct_messages/destroy/:argument',
@ -328,9 +331,9 @@ class Router
foreach (array('xml', 'json', 'rss', 'atom') as $e) { foreach (array('xml', 'json', 'rss', 'atom') as $e) {
$m->connect('api/favorites.'.$e, $m->connect('api/favorites.'.$e,
array('action' => 'api', array('action' => 'api',
'apiaction' => 'favorites', 'apiaction' => 'favorites',
'method' => 'favorites.'.$e)); 'method' => 'favorites.'.$e));
} }
// notifications // notifications
@ -415,7 +418,7 @@ class Router
$match = $this->m->match($path); $match = $this->m->match($path);
} catch (Net_URL_Mapper_InvalidException $e) { } catch (Net_URL_Mapper_InvalidException $e) {
common_log(LOG_ERR, "Problem getting route for $path - " . common_log(LOG_ERR, "Problem getting route for $path - " .
$e->getMessage()); $e->getMessage());
$cac = new ClientErrorAction("Page not found.", 404); $cac = new ClientErrorAction("Page not found.", 404);
$cac->showPage(); $cac->showPage();
} }
@ -438,10 +441,11 @@ class Router
// Due to a bug in the Net_URL_Mapper code, the returned URL may // Due to a bug in the Net_URL_Mapper code, the returned URL may
// contain a malformed query of the form ?p1=v1?p2=v2?p3=v3. We // contain a malformed query of the form ?p1=v1?p2=v2?p3=v3. We
// repair that here rather than modifying the upstream code... // repair that here rather than modifying the upstream code...
$qpos = strpos($url,'?');
$qpos = strpos($url, '?');
if ($qpos !== false) { if ($qpos !== false) {
$url = substr($url, 0, $qpos+1) . $url = substr($url, 0, $qpos+1) .
str_replace('?', '&', substr($url, $qpos+1)); str_replace('?', '&', substr($url, $qpos+1));
} }
return $url; return $url;
} }

View File

@ -94,11 +94,11 @@ class Rss10Action extends Action
function handle($args) function handle($args)
{ {
// Get the list of notices
$this->notices = $this->getNotices();
// Parent handling, including cache check // Parent handling, including cache check
parent::handle($args); parent::handle($args);
$this->showRss($this->limit); // Get the list of notices
$this->notices = $this->getNotices($this->limit);
$this->showRss();
} }
/** /**
@ -132,15 +132,13 @@ class Rss10Action extends Action
return null; return null;
} }
function showRss($limit=0) function showRss()
{ {
$notices = $this->getNotices($limit);
$this->initRss(); $this->initRss();
$this->showChannel($notices); $this->showChannel();
$this->showImage(); $this->showImage();
foreach ($notices as $n) { foreach ($this->notices as $n) {
$this->showItem($n); $this->showItem($n);
} }
@ -148,7 +146,7 @@ class Rss10Action extends Action
$this->endRss(); $this->endRss();
} }
function showChannel($notices) function showChannel()
{ {
$channel = $this->getChannel(); $channel = $this->getChannel();
@ -167,7 +165,7 @@ class Rss10Action extends Action
$this->elementStart('items'); $this->elementStart('items');
$this->elementStart('rdf:Seq'); $this->elementStart('rdf:Seq');
foreach ($notices as $notice) { foreach ($this->notices as $notice) {
$this->element('sioct:MicroblogPost', array('rdf:resource' => $notice->uri)); $this->element('sioct:MicroblogPost', array('rdf:resource' => $notice->uri));
} }

View File

@ -238,21 +238,6 @@ class TwitterapiAction extends Action
$this->elementEnd('item'); $this->elementEnd('item');
} }
function show_twitter_atom_entry($entry)
{
$this->elementStart('entry');
$this->element('title', null, $entry['title']);
$this->element('content', array('type' => 'html'), $entry['content']);
$this->element('id', null, $entry['id']);
$this->element('published', null, $entry['published']);
$this->element('updated', null, $entry['updated']);
$this->element('link', array('href' => $entry['link'], 'rel' => 'alternate', 'type' => 'text/html'), null);
$this->elementStart('author');
$this->element('name', null, $entry['author']);
$this->elementEnd('author');
$this->elementEnd('entry');
}
function show_json_objects($objects) function show_json_objects($objects)
{ {
print(json_encode($objects)); print(json_encode($objects));
@ -383,7 +368,7 @@ class TwitterapiAction extends Action
} }
if (!is_null($selfuri)) { if (!is_null($selfuri)) {
$this->element('link', array('href' => $selfuri, $this->element('link', array('href' => $selfuri,
'rel' => 'self', 'type' => 'application/atom+xml'), null); 'rel' => 'self', 'type' => 'application/atom+xml'), null);
} }
@ -392,13 +377,11 @@ class TwitterapiAction extends Action
if (is_array($notice)) { if (is_array($notice)) {
foreach ($notice as $n) { foreach ($notice as $n) {
$entry = $this->twitter_rss_entry_array($n); $this->raw($n->asAtomEntry());
$this->show_twitter_atom_entry($entry);
} }
} else { } else {
while ($notice->fetch()) { while ($notice->fetch()) {
$entry = $this->twitter_rss_entry_array($notice); $this->raw($notice->asAtomEntry());
$this->show_twitter_atom_entry($entry);
} }
} }
@ -578,13 +561,16 @@ class TwitterapiAction extends Action
function init_twitter_atom() function init_twitter_atom()
{ {
$this->startXML(); $this->startXML();
$this->elementStart('feed', array('xmlns' => 'http://www.w3.org/2005/Atom', 'xml:lang' => 'en-US')); // FIXME: don't hardcode the language here!
$this->elementStart('feed', array('xmlns' => 'http://www.w3.org/2005/Atom',
'xml:lang' => 'en-US',
'xmlns:thr' => 'http://purl.org/syndication/thread/1.0'));
} }
function end_twitter_atom() function end_twitter_atom()
{ {
$this->endXML();
$this->elementEnd('feed'); $this->elementEnd('feed');
$this->endXML();
} }
function show_profile($profile, $content_type='xml', $notice=null) function show_profile($profile, $content_type='xml', $notice=null)

View File

@ -850,7 +850,7 @@ function common_redirect($url, $code=307)
303 => "See Other", 303 => "See Other",
307 => "Temporary Redirect"); 307 => "Temporary Redirect");
header("Status: ${code} $status[$code]"); header('HTTP/1.1 '.$code.' '.$status[$code]);
header("Location: $url"); header("Location: $url");
$xo = new XMLOutputter(); $xo = new XMLOutputter();

View File

@ -105,12 +105,13 @@ class LinkbackPlugin extends Plugin
$pb = $match[1]; $pb = $match[1];
} }
$tb = $this->getTrackback($result->body, $result->final_url); if (!empty($pb)) {
if (!empty($tb)) {
$this->trackback($result->final_url, $tb);
} else if (!empty($pb)) {
$this->pingback($result->final_url, $pb); $this->pingback($result->final_url, $pb);
} else {
$tb = $this->getTrackback($result->body, $result->final_url);
if (!empty($tb)) {
$this->trackback($result->final_url, $tb);
}
} }
return $orig; return $orig;

View File

@ -0,0 +1,104 @@
<?php
/**
* Laconica, the distributed open-source microblogging tool
*
* Plugin to use Piwik Analytics
*
* PHP version 5
*
* LICENCE: This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* @category Plugin
* @package Laconica
* @author Evan Prodromou <evan@controlyourself.ca>
* @author Tobias Diekershoff <tobias.diekershoff@gmx.net>
* @copyright 2008 Control Yourself, Inc.
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
* @link http://laconi.ca/
*/
if (!defined('LACONICA')) {
exit(1);
}
/**
* Plugin to use Piwik Analytics (based on the Google Analytics plugin by Evan)
*
* This plugin will spoot out the correct JavaScript spell to invoke
* Piwik Analytics on a page.
*
* To use this plugin please add the following three lines to your config.php
*
* require_once('plugins/PiwikAnalyticsPlugin.php');
* $pa = new PiwikAnalyticsPlugin("example.com/piwik/","id");
*
* exchange example.com/piwik/ with the url to your piwik installation and
* make sure you don't forget the final /
* exchange id with the ID your laconica installation has in your Piwik analytics
*
* @category Plugin
* @package Laconica
* @author Tobias Diekershoff <tobias.diekershoff@gmx.net>
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
* @link http://laconi.ca/
*
* @see Event
*/
class PiwikAnalyticsPlugin extends Plugin
{
/** the base of your Piwik installation */
var $piwikroot = null;
/** the Piwik Id of your laconica installation */
var $piwikId = null;
/**
* constructor
*
* @param string $root Piwik root URL
* @param string $id Piwik ID of this app
*/
function __construct($root=null, $id=null)
{
$this->piwikroot = $root;
$this->piwikid = $id;
parent::__construct();
}
/**
* Called when all scripts have been shown
*
* @param Action $action Current action
*
* @return boolean ignored
*/
function onEndShowScripts($action)
{
$js1 = 'var pkBaseURL = (("https:" == document.location.protocol) ? "https://'.
$this->piwikroot.'" : "http://'.$this->piwikroot.
'"); document.write(unescape("%3Cscript src=\'" + pkBaseURL + "piwik.js\''.
' type=\'text/javascript\'%3E%3C/script%3E"));';
$js2 = 'piwik_action_name = ""; piwik_idsite = '.$this->piwikid.
'; piwik_url = pkBaseURL + "piwik.php"; piwik_log(piwik_action_name, piwik_idsite, piwik_url);';
$action->elementStart('script', array('type' => 'text/javascript'));
$action->raw($js1);
$action->elementEnd('script');
$action->elementStart('script', array('type' => 'text/javascript'));
$action->raw($js2);
$action->elementEnd('script');
return true;
}
}

View File

@ -150,7 +150,9 @@ font-weight:bold;
#form_openid_login legend, #form_openid_login legend,
#form_search legend, #form_search legend,
#form_invite legend, #form_invite legend,
#form_notice_delete legend { #form_notice_delete legend,
#form_password_recover legend,
#form_password_change legend {
display:none; display:none;
} }
@ -214,6 +216,9 @@ margin-right:0;
address .fn { address .fn {
font-weight:bold; font-weight:bold;
} }
address img + .fn {
display:none;
}
#header { #header {
width:100%; width:100%;
@ -419,6 +424,7 @@ padding:0;
display:none; display:none;
} }
#form_notice textarea { #form_notice textarea {
float:left;
border-radius:7px; border-radius:7px;
-moz-border-radius:7px; -moz-border-radius:7px;
-webkit-border-radius:7px; -webkit-border-radius:7px;
@ -429,30 +435,19 @@ padding:7px 7px 16px 7px;
} }
#form_notice label { #form_notice label {
display:block; display:block;
float:left;
font-size:1.3em; font-size:1.3em;
margin-bottom:7px; margin-bottom:7px;
} }
#form_notice .form_data li {
float:left;
}
#form_notice #notice_attach_file label,
#form_notice #notice_submit label { #form_notice #notice_submit label {
display:none; display:none;
} }
#form_notice #notice_attachment {
margin-top:25px;
margin-left:4px;
}
#form_notice .form_note { #form_notice .form_note {
position:absolute; position:absolute;
top:99px; top:99px;
right:98px; right:98px;
z-index:9; z-index:9;
} }
#form_notice .form_note dt { #form_notice .form_note dt {
font-weight:bold; font-weight:bold;
display:none; display:none;
@ -462,42 +457,19 @@ font-weight:bold;
line-height:1.15; line-height:1.15;
padding:1px 2px; padding:1px 2px;
} }
#form_notice #notice_action-submit {
#form_notice #notice_data-attach_view { width:60px;
position:absolute; padding:8px;
top:25px;
right:30px;
margin-left:4px;
padding:0;
width:16px;
height:16px;
border:0;
text-indent:-9999px;
}
#form_notice .form_actions {
position:absolute; position:absolute;
bottom:0; bottom:0;
right:0; right:0;
} }
#form_notice .form_actions input.submit { #form_notice label[for=to] {
width:60px;
padding:8px;
}
#form_notice li {
margin-bottom:0;
}
#form_notice #notice_to {
margin-bottom:7px;
}
#notice_to label {
float:left;
margin-right:18px;
margin-top:11px; margin-top:11px;
} }
#notice_to select { #form_notice select[id=to] {
margin-bottom:7px;
margin-left:18px;
float:left; float:left;
} }
/*end FORM NOTICE*/ /*end FORM NOTICE*/

View File

@ -9,3 +9,6 @@ margin-left:0;
.entity_profile .entity_depiction { .entity_profile .entity_depiction {
margin-bottom:123px; margin-bottom:123px;
} }
.notice div.entry-content {
width:63%;
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 673 B

View File

@ -19,9 +19,6 @@ font-size:1em;
address { address {
margin-right:71px; margin-right:71px;
} }
address .fn {
display:none;
}
input, textarea, select, option { input, textarea, select, option {
font-family: "Lucida Sans Unicode", "Lucida Grande", sans-serif; font-family: "Lucida Sans Unicode", "Lucida Grande", sans-serif;
@ -94,6 +91,11 @@ color:#333;
#form_notice.warning #notice_text-count { #form_notice.warning #notice_text-count {
color:#000; color:#000;
} }
#form_notice.processing #notice_action-submit {
background:#fff url(../../base/images/icons/icon_processing.gif) no-repeat 47% 47%;
cursor:wait;
text-indent:-9999px;
}
#nav_register a { #nav_register a {

View File

@ -19,9 +19,6 @@ font-size:1em;
address { address {
margin-right:71px; margin-right:71px;
} }
address .fn {
display:none;
}
input, textarea, select, option { input, textarea, select, option {
font-family: "Lucida Sans Unicode", "Lucida Grande", sans-serif; font-family: "Lucida Sans Unicode", "Lucida Grande", sans-serif;
@ -94,7 +91,11 @@ color:#333;
#form_notice.warning #notice_text-count { #form_notice.warning #notice_text-count {
color:#000; color:#000;
} }
#form_notice.processing #notice_action-submit {
background:#fff url(../../base/images/icons/icon_processing.gif) no-repeat 47% 47%;
cursor:wait;
text-indent:-9999px;
}
#nav_register a { #nav_register a {
text-decoration:none; text-decoration:none;