Some toolbar upgrades
@@ -23,7 +23,7 @@
|
||||
# Jacascript files to be compressified
|
||||
js_targets = jquery.js jquery.json.js jquery.reddit.js reddit.js
|
||||
# CSS targets
|
||||
css_targets = reddit.css reddit-ie6-hax.css
|
||||
css_targets = reddit.css reddit-ie6-hax.css reddit-ie7-hax.css
|
||||
|
||||
SED=sed
|
||||
|
||||
|
||||
@@ -134,8 +134,16 @@ def make_map(global_conf={}, app_conf={}):
|
||||
requirements=dict(action="help|blog"))
|
||||
mc('/help/:anything', controller='embed', action='help')
|
||||
|
||||
mc('/:action', controller='toolbar',
|
||||
requirements=dict(action="goto|toolbar"))
|
||||
mc('/goto', controller='toolbar', action='goto')
|
||||
mc('/tb/:id', controller='toolbar', action='tb')
|
||||
mc('/toolbar/:action', controller='toolbar',
|
||||
requirements=dict(action="toolbar|inner|login"))
|
||||
mc('/toolbar/comments/:id', controller='toolbar', action='comments')
|
||||
|
||||
mc('/s/*rest', controller='toolbar', action='s')
|
||||
# additional toolbar-related rules just above the catchall
|
||||
|
||||
mc('/d/:what', controller='api', action='bookmarklet')
|
||||
|
||||
mc('/resetpassword/:key', controller='front',
|
||||
action='resetpassword')
|
||||
@@ -150,8 +158,6 @@ def make_map(global_conf={}, app_conf={}):
|
||||
mc('/api/:action/:url_user', controller='api',
|
||||
requirements=dict(action="login|register"))
|
||||
mc('/api/:action', controller='api')
|
||||
|
||||
mc('/d/:what', controller='api', action='bookmarklet')
|
||||
|
||||
mc('/captcha/:iden', controller='captcha', action='captchaimg')
|
||||
|
||||
@@ -175,6 +181,15 @@ def make_map(global_conf={}, app_conf={}):
|
||||
# displayed properly.
|
||||
mc('/error/document/:id', controller='error', action="document")
|
||||
|
||||
# these should be near the buttom, because they should only kick
|
||||
# in if everything else fails. It's the attempted catch-all
|
||||
# reddit.com/http://... and reddit.com/34fr, but these redirect to
|
||||
# the less-guessy versions at /s/ and /tb/
|
||||
mc('/:linkoid', controller='toolbar', action='linkoid',
|
||||
requirements=dict(linkoid='[0-9a-z]{1,6}'))
|
||||
mc('/:urloid', controller='toolbar', action='urloid',
|
||||
requirements=dict(urloid=r'(\w+\.\w{2,}|https?).*'))
|
||||
|
||||
mc("/*url", controller='front', action='catchall')
|
||||
|
||||
return map
|
||||
|
||||
@@ -33,7 +33,7 @@ import r2.models.thing_changes as tc
|
||||
from r2.controllers import ListingController
|
||||
|
||||
from r2.lib.utils import get_title, sanitize_url, timeuntil, set_last_modified
|
||||
from r2.lib.utils import query_string, to36, timefromnow
|
||||
from r2.lib.utils import query_string, to36, timefromnow, link_from_url
|
||||
from r2.lib.wrapped import Wrapped
|
||||
from r2.lib.pages import FriendList, ContributorList, ModList, \
|
||||
BannedList, BoringPage, FormPage, NewLink, CssError, UploadedImage
|
||||
@@ -55,25 +55,6 @@ from md5 import md5
|
||||
|
||||
from r2.lib.promote import promote, unpromote, get_promoted
|
||||
|
||||
def link_listing_by_url(url, count = None):
|
||||
"""
|
||||
Generates a listing of links which share a common url
|
||||
"""
|
||||
links = ()
|
||||
try:
|
||||
if url:
|
||||
links = list(tup(Link._by_url(url, sr = c.site)))
|
||||
links.sort(key = lambda x: -x._score)
|
||||
if count is not None:
|
||||
links = links[:count]
|
||||
except NotFound:
|
||||
pass
|
||||
names = [l._fullname for l in links]
|
||||
builder = IDBuilder(names, num = 25)
|
||||
return LinkListing(builder).listing()
|
||||
|
||||
|
||||
|
||||
class ApiController(RedditController):
|
||||
"""
|
||||
Controller which deals with almost all AJAX site interaction.
|
||||
@@ -95,10 +76,14 @@ class ApiController(RedditController):
|
||||
count = VLimit('limit'))
|
||||
def GET_info(self, link, count):
|
||||
"""
|
||||
Get's a listing of links which have the provided url.
|
||||
Gets a listing of links which have the provided url.
|
||||
"""
|
||||
listing = link_listing_by_url(request.params.get('url'),
|
||||
count = count)
|
||||
if not link or 'url' not in request.params:
|
||||
return abort(404, 'not found')
|
||||
|
||||
links = link_from_url(request.params.get('url'), filter_spam = False)
|
||||
builder = IDBuilder([link._fullname for link in links], num = count)
|
||||
listing = LinkListing(builder, nextprev = False).listing()
|
||||
return BoringPage(_("API"), content = listing).render()
|
||||
|
||||
@validatedForm(VCaptcha(),
|
||||
@@ -169,8 +154,9 @@ class ApiController(RedditController):
|
||||
url = VUrl(['url', 'sr']),
|
||||
title = VTitle('title'),
|
||||
save = VBoolean('save'),
|
||||
then = VOneOf('then', ('tb', 'comments'), default='comments')
|
||||
)
|
||||
def POST_submit(self, form, jquery, url, title, save, sr, ip):
|
||||
def POST_submit(self, form, jquery, url, title, save, sr, ip, then):
|
||||
if isinstance(url, (unicode, str)):
|
||||
form.set_inputs(url = url)
|
||||
|
||||
@@ -245,13 +231,12 @@ class ApiController(RedditController):
|
||||
# flag search indexer that something has changed
|
||||
tc.changed(l)
|
||||
|
||||
# make_permalink is designed for links that can be set to _top
|
||||
# here, we need to generate an ajax redirect as if we were not on a
|
||||
# cname.
|
||||
cname = c.cname
|
||||
c.cname = False
|
||||
path = l.make_permalink_slow()
|
||||
c.cname = cname
|
||||
if then == 'comments':
|
||||
path = add_sr(l.make_permalink_slow())
|
||||
elif then == 'tb':
|
||||
form.attr('target', '_top')
|
||||
path = add_sr('/tb/%s' % l._id36)
|
||||
|
||||
form.redirect(path)
|
||||
|
||||
def _login(self, form, user, dest='', rem = None):
|
||||
@@ -706,7 +691,9 @@ class ApiController(RedditController):
|
||||
errors.BANNED_IP in c.errors or
|
||||
errors.CHEATER in c.errors)
|
||||
# TODO: temporary hack until we migrate the rest of the vote data
|
||||
if thing and thing._date > datetime(2009, 4, 17, 0, 0, 0, 0, g.tz):
|
||||
if thing and thing._date < datetime(2009, 4, 17, 0, 0, 0, 0, g.tz):
|
||||
g.log.debug("POST_vote: ignoring old vote on %s" % thing._fullname)
|
||||
elif thing:
|
||||
dir = (True if dir > 0
|
||||
else False if dir < 0
|
||||
else None)
|
||||
@@ -1372,6 +1359,18 @@ class ApiController(RedditController):
|
||||
return UploadedImage(_('saved'), thumbnail_url(link), "",
|
||||
errors = errors).render()
|
||||
|
||||
@noresponse()
|
||||
def POST_tb_commentspanel_show(self):
|
||||
# this preference is allowed for non-logged-in users
|
||||
c.user.pref_frame_commentspanel = True
|
||||
c.user._commit()
|
||||
|
||||
@noresponse()
|
||||
def POST_tb_commentspanel_hide(self):
|
||||
# this preference is allowed for non-logged-in users
|
||||
c.user.pref_frame_commentspanel = False
|
||||
c.user._commit()
|
||||
|
||||
@validatedForm(promoted = VByName('ids', thing_cls = Link, multiple = True))
|
||||
def POST_onload(self, form, jquery, promoted, *a, **kw):
|
||||
# make sure that they are really promoted
|
||||
|
||||
@@ -113,6 +113,8 @@ class ErrorController(RedditController):
|
||||
|
||||
def send404(self):
|
||||
c.response.status_code = 404
|
||||
if 'usable_error_content' in request.environ:
|
||||
return request.environ['usable_error_content']
|
||||
if c.site._spam and not c.user_is_admin:
|
||||
message = (strings.banned_subreddit % dict(link = '/feedback'))
|
||||
|
||||
|
||||
@@ -22,12 +22,12 @@
|
||||
from validator import *
|
||||
from pylons.i18n import _, ungettext
|
||||
from reddit_base import RedditController, base_listing
|
||||
from api import link_listing_by_url
|
||||
from r2 import config
|
||||
from r2.models import *
|
||||
from r2.lib.pages import *
|
||||
from r2.lib.menus import *
|
||||
from r2.lib.utils import to36, sanitize_url, check_cheating, title_to_url, query_string, UrlParser
|
||||
from r2.lib.utils import to36, sanitize_url, check_cheating, title_to_url
|
||||
from r2.lib.utils import query_string, UrlParser, link_from_url
|
||||
from r2.lib.template_helpers import get_domain
|
||||
from r2.lib.emailer import has_opted_out, Email
|
||||
from r2.lib.db.operators import desc
|
||||
@@ -76,20 +76,20 @@ class FrontController(RedditController):
|
||||
|
||||
def GET_random(self):
|
||||
"""The Serendipity button"""
|
||||
n = rand.randint(0, 9)
|
||||
sort = 'new' if n > 5 else 'hot'
|
||||
sort = 'new' if rand.choice((True,False)) else 'hot'
|
||||
links = c.site.get_links(sort, 'all')
|
||||
if isinstance(links, thing.Query):
|
||||
links._limit = 25
|
||||
links = [x._fullname for x in links]
|
||||
links._limit = 25
|
||||
links = [x._fullname for x in links]
|
||||
else:
|
||||
links = links[:25]
|
||||
links = list(links)[:25]
|
||||
|
||||
if links:
|
||||
name = links[rand.randint(0, min(24, len(links)-1))]
|
||||
name = rand.choice(links)
|
||||
link = Link._by_fullname(name, data = True)
|
||||
return self.redirect(link.url)
|
||||
return self.redirect(add_sr("/tb/" + link._id36))
|
||||
else:
|
||||
return self.redirect('/')
|
||||
return self.redirect(add_sr('/'))
|
||||
|
||||
def GET_password(self):
|
||||
"""The 'what is my password' page"""
|
||||
@@ -138,8 +138,8 @@ class FrontController(RedditController):
|
||||
#check for 304
|
||||
self.check_modified(article, 'comments')
|
||||
|
||||
# if there is a focal comment, communicate down to comment_skeleton.html who
|
||||
# that will be
|
||||
# if there is a focal comment, communicate down to
|
||||
# comment_skeleton.html who that will be
|
||||
if comment:
|
||||
c.focal_comment = comment._id36
|
||||
|
||||
@@ -150,7 +150,9 @@ class FrontController(RedditController):
|
||||
|
||||
check_cheating('comments')
|
||||
|
||||
# figure out number to show based on the menu
|
||||
# figure out number to show based on the menu (when num_comments
|
||||
# is 'true', the user wants to temporarily override their
|
||||
# comments limit pref
|
||||
user_num = c.user.pref_num_comments or g.num_comments
|
||||
num = g.max_comments if num_comments == 'true' else user_num
|
||||
|
||||
@@ -411,8 +413,6 @@ class FrontController(RedditController):
|
||||
|
||||
return builder.total_num, timing, res
|
||||
|
||||
|
||||
|
||||
def GET_login(self):
|
||||
"""The /login form. No link to this page exists any more on
|
||||
the site (all actions invoking it now go through the login
|
||||
@@ -432,10 +432,10 @@ class FrontController(RedditController):
|
||||
|
||||
@validate(VUser(),
|
||||
VModhash())
|
||||
def POST_logout(self):
|
||||
def POST_logout(self, dest = None):
|
||||
"""wipe login cookie and redirect to referer."""
|
||||
self.logout()
|
||||
dest = request.referer or '/'
|
||||
dest = request.post.get('dest','') or request.referer or '/'
|
||||
return self.redirect(dest)
|
||||
|
||||
|
||||
@@ -474,38 +474,25 @@ class FrontController(RedditController):
|
||||
@validate(VUser(),
|
||||
VSRSubmitPage(),
|
||||
url = VRequired('url', None),
|
||||
title = VRequired('title', None))
|
||||
def GET_submit(self, url, title):
|
||||
title = VRequired('title', None),
|
||||
then = VOneOf('then', ('tb','comments'), default = 'comments'))
|
||||
def GET_submit(self, url, title, then):
|
||||
"""Submit form."""
|
||||
if url and not request.get.get('resubmit'):
|
||||
# check to see if the url has already been submitted
|
||||
listing = link_listing_by_url(url)
|
||||
redirect_link = None
|
||||
if listing.things:
|
||||
# if there is only one submission, the operation is clear
|
||||
if len(listing.things) == 1:
|
||||
redirect_link = listing.things[0]
|
||||
# if there is more than one, check the users' subscriptions
|
||||
else:
|
||||
subscribed = [l for l in listing.things
|
||||
if c.user_is_loggedin
|
||||
and l.subreddit.is_subscriber_defaults(c.user)]
|
||||
links = link_from_url(url)
|
||||
if links and len(links) == 1:
|
||||
return self.redirect(links[0].already_submitted_link)
|
||||
elif links:
|
||||
builder = IDBuilder([link._fullname for link in links])
|
||||
listing = LinkListing(builder, nextprev=False).listing()
|
||||
infotext = (strings.multiple_submitted
|
||||
% links[0].resubmit_link())
|
||||
res = BoringPage(_("seen it"),
|
||||
content = listing,
|
||||
infotext = infotext).render()
|
||||
return res
|
||||
|
||||
#if there is only 1 link to be displayed, just go there
|
||||
if len(subscribed) == 1:
|
||||
redirect_link = subscribed[0]
|
||||
else:
|
||||
infotext = strings.multiple_submitted % \
|
||||
listing.things[0].resubmit_link()
|
||||
res = BoringPage(_("seen it"),
|
||||
content = listing,
|
||||
infotext = infotext).render()
|
||||
return res
|
||||
|
||||
# we've found a link already. Redirect to its permalink page
|
||||
if redirect_link:
|
||||
return self.redirect(redirect_link.already_submitted_link)
|
||||
|
||||
captcha = Captcha() if c.user.needs_captcha() else None
|
||||
sr_names = Subreddit.submit_sr_names(c.user) if c.default_sr else ()
|
||||
|
||||
@@ -513,7 +500,8 @@ class FrontController(RedditController):
|
||||
content=NewLink(url=url or '',
|
||||
title=title or '',
|
||||
subreddits = sr_names,
|
||||
captcha=captcha)).render()
|
||||
captcha=captcha,
|
||||
then = then)).render()
|
||||
|
||||
def _render_opt_in_out(self, msg_hash, leave):
|
||||
"""Generates the form for an optin/optout page"""
|
||||
|
||||
@@ -47,7 +47,7 @@ from r2.lib.tracking import encrypt, decrypt
|
||||
|
||||
NEVER = 'Thu, 31 Dec 2037 23:59:59 GMT'
|
||||
|
||||
cache_affecting_cookies = ('reddit_first','over18')
|
||||
cache_affecting_cookies = ('reddit_first','over18','_options')
|
||||
|
||||
r_subnet = re.compile("^(\d+\.\d+)\.\d+\.\d+$")
|
||||
|
||||
@@ -73,7 +73,7 @@ class Cookie(object):
|
||||
|
||||
class UnloggedUser(FakeAccount):
|
||||
_cookie = 'options'
|
||||
allowed_prefs = ('pref_content_langs', 'pref_lang')
|
||||
allowed_prefs = ('pref_content_langs', 'pref_lang', 'pref_frame_commentspanel')
|
||||
|
||||
def __init__(self, browser_langs, *a, **kw):
|
||||
FakeAccount.__init__(self, *a, **kw)
|
||||
@@ -90,6 +90,7 @@ class UnloggedUser(FakeAccount):
|
||||
self._defaults = self._defaults.copy()
|
||||
self._defaults['pref_lang'] = lang
|
||||
self._defaults['pref_content_langs'] = content_langs
|
||||
self._defaults['pref_frame_commentspanel'] = False
|
||||
self._load()
|
||||
|
||||
@property
|
||||
|
||||
@@ -21,31 +21,228 @@
|
||||
################################################################################
|
||||
from reddit_base import RedditController
|
||||
from r2.lib.pages import *
|
||||
from r2.models import *
|
||||
from r2.lib.menus import CommentSortMenu
|
||||
from r2.lib.filters import spaceCompress
|
||||
from r2.lib.memoize import memoize
|
||||
from r2.lib.template_helpers import add_sr
|
||||
from r2.lib import utils
|
||||
from validator import *
|
||||
from pylons import c
|
||||
from pylons import c, Response
|
||||
|
||||
import string
|
||||
|
||||
# strips /r/foo/, /s/, or both
|
||||
strip_sr = re.compile('^/r/[a-zA-Z0-9_-]+')
|
||||
strip_s_path = re.compile('^/s/')
|
||||
leading_slash = re.compile('^/+')
|
||||
has_protocol = re.compile('^https?:')
|
||||
need_insert_slash = re.compile('^https?:/[^/]')
|
||||
def demangle_url(path):
|
||||
# there's often some URL mangling done by the stack above us, so
|
||||
# let's clean up the URL before looking it up
|
||||
path = strip_sr.sub('', path)
|
||||
path = strip_s_path.sub('', path)
|
||||
path = leading_slash.sub("", path)
|
||||
|
||||
if not has_protocol.match(path):
|
||||
path = 'http://%s' % path
|
||||
|
||||
if need_insert_slash.match(path):
|
||||
path = string.replace(path, '/', '//', 1)
|
||||
|
||||
path = utils.sanitize_url(path)
|
||||
|
||||
return path
|
||||
|
||||
def force_html():
|
||||
"""Because we can take URIs like /s/http://.../foo.png, and we can
|
||||
guarantee that the toolbar will never be used with a non-HTML
|
||||
render style, we don't want to interpret the extension from the
|
||||
target URL. So here we rewrite Middleware's interpretation of
|
||||
the extension to force it to be HTML
|
||||
"""
|
||||
|
||||
c.render_style = 'html'
|
||||
c.extension = None
|
||||
c.content_type = 'text/html; charset=UTF-8'
|
||||
|
||||
def auto_expand_panel(link):
|
||||
if not link.num_comments:
|
||||
return False
|
||||
else:
|
||||
return c.user.pref_frame_commentspanel
|
||||
|
||||
@memoize('toolbar.get_title', time = 500)
|
||||
def get_title(url):
|
||||
"""Find the <title> in the page contained at 'url'. Copied here
|
||||
from utils so that we can memoize it"""
|
||||
return utils.get_title(url)
|
||||
|
||||
class ToolbarController(RedditController):
|
||||
|
||||
@validate(link = VByName('id'))
|
||||
def GET_toolbar(self, link):
|
||||
if not link: return self.abort404()
|
||||
link_builder = IDBuilder((link._fullname,))
|
||||
link_listing = LinkListing(link_builder, nextprev=False).listing()
|
||||
res = FrameToolbar(link = link_listing.things[0]).render()
|
||||
return spaceCompress(res)
|
||||
|
||||
@validate(link = VByName('id'),
|
||||
@validate(link1 = VByName('id'),
|
||||
link2 = VLink('id', redirect = False))
|
||||
def GET_goto(self, link, link2):
|
||||
link = link2 if link2 else link
|
||||
def GET_goto(self, link1, link2):
|
||||
"""Support old /goto?id= urls. deprecated"""
|
||||
link = link2 if link2 else link1
|
||||
if link:
|
||||
link._load()
|
||||
if c.user and c.user.pref_frame:
|
||||
return Frame(title = link.title,
|
||||
url = link.url,
|
||||
fullname = link._fullname).render()
|
||||
else:
|
||||
return self.redirect(link.url)
|
||||
return self.redirect(add_sr("/tb/" + link._id36))
|
||||
return self.abort404()
|
||||
|
||||
@validate(link = VLink('id'))
|
||||
def GET_tb(self, link):
|
||||
"/tb/$id36, show a given link with the toolbar"
|
||||
if not link:
|
||||
return self.abort404()
|
||||
|
||||
res = Frame(title = link.title,
|
||||
url = link.url,
|
||||
fullname = link._fullname)
|
||||
return spaceCompress(res.render())
|
||||
|
||||
def GET_s(self, rest):
|
||||
"""/s/http://..., show a given URL with the toolbar. if it's
|
||||
submitted, redirect to /tb/$id36"""
|
||||
force_html()
|
||||
path = demangle_url(request.fullpath)
|
||||
|
||||
if not path:
|
||||
# it was malformed
|
||||
self.abort404()
|
||||
|
||||
link = utils.link_from_url(path, multiple = False)
|
||||
|
||||
if c.cname and not c.authorized_cname:
|
||||
# In this case, we make some bad guesses caused by the
|
||||
# cname frame on unauthorised cnames.
|
||||
# 1. User types http://foo.com/http://myurl?cheese=brie
|
||||
# (where foo.com is an unauthorised cname)
|
||||
# 2. We generate a frame that points to
|
||||
# http://www.reddit.com/r/foo/http://myurl?cnameframe=0.12345&cheese=brie
|
||||
# 3. Because we accept everything after the /r/foo/, and
|
||||
# we've now parsed, modified, and reconstituted that
|
||||
# URL to add cnameframe, we really can't make any good
|
||||
# assumptions about what we've done to a potentially
|
||||
# already broken URL, and we can't assume that we've
|
||||
# rebuilt it in the way that it was originally
|
||||
# submitted (if it was)
|
||||
# We could try to work around this with more guesses (by
|
||||
# having demangle_url try to remove that param, hoping
|
||||
# that it's not already a malformed URL, and that we
|
||||
# haven't re-ordered the GET params, removed
|
||||
# double-slashes, etc), but for now, we'll just refuse to
|
||||
# do this operation
|
||||
return self.abort404()
|
||||
|
||||
if link:
|
||||
# we were able to find it, let's send them to the
|
||||
# link-id-based URL so that their URL is reusable
|
||||
return self.redirect(add_sr("/tb/" + link._id36))
|
||||
|
||||
title = get_title(path)
|
||||
if not title:
|
||||
title = utils.domain(path)
|
||||
res = Frame(title = title, url = path)
|
||||
|
||||
# we don't want clients to think that this URL is actually a
|
||||
# valid URL for search-indexing or the like
|
||||
c.response = Response()
|
||||
c.response.status_code = 404
|
||||
request.environ['usable_error_content'] = spaceCompress(res.render())
|
||||
|
||||
return c.response
|
||||
|
||||
@validate(link = VLink('id'))
|
||||
def GET_comments(self, link):
|
||||
if not link:
|
||||
self.abort404()
|
||||
if not link.subreddit_slow.can_view(c.user):
|
||||
abort(403, 'forbidden')
|
||||
|
||||
def builder_wrapper(cm):
|
||||
w = Wrapped(cm)
|
||||
w.render_class = StarkComment
|
||||
w.target = "_top"
|
||||
return w
|
||||
|
||||
link_builder = IDBuilder((link._fullname,))
|
||||
link_listing = LinkListing(link_builder, nextprev=False).listing()
|
||||
links = link_listing.things[0],
|
||||
if not links:
|
||||
# they aren't allowed to see this link
|
||||
return self.abort(403, 'forbidden')
|
||||
link = links[0]
|
||||
|
||||
res = FrameToolbar(link = link,
|
||||
title = link.title,
|
||||
url = link.url)
|
||||
|
||||
|
||||
b = TopCommentBuilder(link, CommentSortMenu.operator('top'),
|
||||
wrap = builder_wrapper)
|
||||
|
||||
listing = NestedListing(b, num = 10, # TODO: add config var
|
||||
parent_name = link._fullname)
|
||||
|
||||
res = RedditMin(content=CommentsPanel(link=link, listing=listing.listing(),
|
||||
expanded = auto_expand_panel(link)))
|
||||
|
||||
return res.render()
|
||||
|
||||
@validate(link = VByName('id'),
|
||||
url = nop('url'))
|
||||
def GET_toolbar(self, link, url):
|
||||
"""The visible toolbar, with voting buttons and all"""
|
||||
if not link:
|
||||
link = utils.link_from_url(url, multiple = False)
|
||||
|
||||
if link:
|
||||
link_builder = IDBuilder((link._fullname,))
|
||||
res = FrameToolbar(link = link_builder.get_items()[0][0],
|
||||
title = link.title,
|
||||
url = link.url,
|
||||
expanded = auto_expand_panel(link))
|
||||
else:
|
||||
res = FrameToolbar(link = None,
|
||||
title = get_title(url),
|
||||
url = url,
|
||||
expanded = False)
|
||||
|
||||
return spaceCompress(res.render())
|
||||
|
||||
@validate(link = VByName('id'))
|
||||
def GET_inner(self, link):
|
||||
"""The intermediate frame that displays the comments side-bar
|
||||
on one side and the link on the other"""
|
||||
if not link:
|
||||
return self.abort404()
|
||||
|
||||
res = InnerToolbarFrame(link = link, expanded = auto_expand_panel(link))
|
||||
return spaceCompress(res.render())
|
||||
|
||||
@validate(link = VLink('linkoid'))
|
||||
def GET_linkoid(self, link):
|
||||
if not link:
|
||||
return self.abort404()
|
||||
return self.redirect(add_sr("/tb/" + link._id36))
|
||||
|
||||
slash_fixer = re.compile('(/s/https?:)/+')
|
||||
@validate(urloid = nop('urloid'))
|
||||
def GET_urloid(self, urloid):
|
||||
# they got here from "/http://..."
|
||||
path = demangle_url(request.fullpath)
|
||||
|
||||
if not path:
|
||||
# malformed URL
|
||||
self.abort404()
|
||||
|
||||
redir_path = add_sr("/s/" + path)
|
||||
force_html()
|
||||
|
||||
# Redirect to http://reddit.com/s/http://google.com
|
||||
# rather than http://reddit.com/s/http:/google.com
|
||||
redir_path = self.slash_fixer.sub(r'\1///', redir_path, 1)
|
||||
# ^^^
|
||||
# 3=2 when it comes to self.redirect()
|
||||
return self.redirect(redir_path)
|
||||
|
||||
|
||||
@@ -115,7 +115,7 @@ fix_url = re.compile('<(http://[^\s\'\"\]\)]+)>')
|
||||
|
||||
#TODO markdown should be looked up in batch?
|
||||
#@memoize('markdown')
|
||||
def safemarkdown(text, nofollow = False):
|
||||
def safemarkdown(text, nofollow=False, target=None):
|
||||
from contrib.markdown import markdown
|
||||
if text:
|
||||
# increase escaping of &, < and > once
|
||||
@@ -133,8 +133,12 @@ def safemarkdown(text, nofollow = False):
|
||||
def href_handler(m):
|
||||
url = m.group(1).replace('&', '&')
|
||||
link = '<a href="%s"' % url
|
||||
if c.cname:
|
||||
|
||||
if target:
|
||||
link += ' target="%s"' % target
|
||||
elif c.cname:
|
||||
link += ' target="_top"'
|
||||
|
||||
if nofollow:
|
||||
link += ' rel="nofollow"'
|
||||
return link
|
||||
|
||||
@@ -99,6 +99,7 @@ menu = MenuHandler(hot = _('hot'),
|
||||
store = _("store"),
|
||||
ad_inq = _("advertise on reddit"),
|
||||
toplinks = _("top links"),
|
||||
random = _('random'),
|
||||
iphone = _("iPhone app"),
|
||||
|
||||
#preferences
|
||||
|
||||
@@ -24,7 +24,7 @@ from r2.models import IDBuilder, LinkListing, Account, Default, FakeSubreddit, S
|
||||
from r2.config import cache
|
||||
from r2.lib.jsonresponse import json_respond
|
||||
from r2.lib.jsontemplates import is_api
|
||||
from pylons.i18n import _
|
||||
from pylons.i18n import _, ungettext
|
||||
from pylons import c, request, g
|
||||
from pylons.controllers.util import abort
|
||||
|
||||
@@ -33,11 +33,13 @@ from r2.lib.captcha import get_iden
|
||||
from r2.lib.filters import spaceCompress, _force_unicode, _force_utf8
|
||||
from r2.lib.menus import NavButton, NamedButton, NavMenu, PageNameNav, JsButton
|
||||
from r2.lib.menus import SubredditButton, SubredditMenu, OffsiteButton, menu
|
||||
from r2.lib.strings import plurals, rand_strings, strings
|
||||
from r2.lib.utils import title_to_url, query_string, UrlParser, to_js
|
||||
from r2.lib.strings import plurals, rand_strings, strings, Score
|
||||
from r2.lib.utils import title_to_url, query_string, UrlParser, to_js, vote_hash
|
||||
from r2.lib.template_helpers import add_sr, get_domain
|
||||
import sys, random, datetime, locale, calendar
|
||||
|
||||
import sys, random, datetime, locale, calendar, re
|
||||
import graph
|
||||
from urllib import quote
|
||||
|
||||
datefmt = _force_utf8(_('%d %b %Y'))
|
||||
|
||||
@@ -71,20 +73,23 @@ class Reddit(Wrapped):
|
||||
|
||||
create_reddit_box = True
|
||||
submit_box = True
|
||||
footer = True
|
||||
searchbox = True
|
||||
extension_handling = True
|
||||
enable_login_cover = True
|
||||
site_tracking = True
|
||||
show_firsttext = True
|
||||
|
||||
def __init__(self, space_compress = True, nav_menus = None, loginbox = True,
|
||||
infotext = '', content = None, title = '', robots = None,
|
||||
show_sidebar = True, **context):
|
||||
show_sidebar = True, footer = True, **context):
|
||||
Wrapped.__init__(self, **context)
|
||||
self.title = title
|
||||
self.robots = robots
|
||||
self.infotext = infotext
|
||||
self.loginbox = True
|
||||
self.show_sidebar = show_sidebar
|
||||
self.footer = footer
|
||||
self.space_compress = space_compress
|
||||
|
||||
#put the sort menus at the top
|
||||
@@ -92,7 +97,7 @@ class Reddit(Wrapped):
|
||||
|
||||
#add the infobar
|
||||
self.infobar = None
|
||||
if c.firsttime and c.site.firsttext and not infotext:
|
||||
if self.show_firsttext and c.firsttime and c.site.firsttext and not infotext:
|
||||
infotext = c.site.firsttext
|
||||
if infotext:
|
||||
self.infobar = InfoBar(message = infotext)
|
||||
@@ -190,6 +195,7 @@ class Reddit(Wrapped):
|
||||
OffsiteButton("rss", dest = '/.rss'),
|
||||
NamedButton("store", False, nocname=True),
|
||||
NamedButton("stats", False, nocname=True),
|
||||
NamedButton('random', False, nocname=False),
|
||||
NamedButton("feedback", False),],
|
||||
title = 'site links', type = 'flat_vert',
|
||||
separator = ''),
|
||||
@@ -297,6 +303,13 @@ class Reddit(Wrapped):
|
||||
"""returns a Wrapped (or renderable) item for the main content div."""
|
||||
return self.content_stack(self.infobar, self.nav_menu, self._content)
|
||||
|
||||
class RedditMin(Reddit):
|
||||
"""a version of Reddit that has no sidebar, toolbar, footer,
|
||||
etc"""
|
||||
footer = False
|
||||
show_sidebar = False
|
||||
show_firsttext = False
|
||||
|
||||
class LoginFormWide(Wrapped):
|
||||
"""generates a login form suitable for the 300px rightbox."""
|
||||
pass
|
||||
@@ -455,6 +468,17 @@ class SearchPage(BoringPage):
|
||||
return self.content_stack(self.searchbar, self.infobar,
|
||||
self.nav_menu, self._content)
|
||||
|
||||
class CommentsPanel(Wrapped):
|
||||
"""the side-panel on the reddit toolbar frame that shows the top
|
||||
comments of a link"""
|
||||
|
||||
def __init__(self, link = None, listing = None, expanded = False, *a, **kw):
|
||||
self.link = link
|
||||
self.listing = listing
|
||||
self.expanded = expanded
|
||||
|
||||
Wrapped.__init__(self, *a, **kw)
|
||||
|
||||
class LinkInfoPage(Reddit):
|
||||
"""Renders the varied /info pages for a link. The Link object is
|
||||
passed via the link argument and the content passed to this class
|
||||
@@ -531,12 +555,8 @@ class LinkInfoPage(Reddit):
|
||||
class LinkInfoBar(Wrapped):
|
||||
"""Right box for providing info about a link."""
|
||||
def __init__(self, a = None):
|
||||
if a:
|
||||
a = Wrapped(a)
|
||||
|
||||
Wrapped.__init__(self, a = a, datefmt = datefmt)
|
||||
|
||||
|
||||
class EditReddit(Reddit):
|
||||
"""Container for the about page for a reddit"""
|
||||
extension_handling= False
|
||||
@@ -880,27 +900,73 @@ class SearchBar(Wrapped):
|
||||
|
||||
|
||||
class Frame(Wrapped):
|
||||
"""Frameset for the FrameToolbar used when a user hits /goto and
|
||||
has pref_toolbar set. The top 30px of the page are dedicated to
|
||||
the toolbar, while the rest of the page will show the results of
|
||||
following the link."""
|
||||
def __init__(self, url='', title='', fullname=''):
|
||||
"""Frameset for the FrameToolbar used when a user hits /tb/. The
|
||||
top 30px of the page are dedicated to the toolbar, while the rest
|
||||
of the page will show the results of following the link."""
|
||||
def __init__(self, url='', title='', fullname=None):
|
||||
if title:
|
||||
title = (_('%(site_title)s via %(domain)s')
|
||||
% dict(site_title = _force_unicode(title),
|
||||
domain = g.domain))
|
||||
else:
|
||||
title = g.domain
|
||||
|
||||
Wrapped.__init__(self, url = url, title = title, fullname = fullname)
|
||||
|
||||
dorks_re = re.compile(r"https?://?([-\w.]*\.)?digg\.com/\w+$")
|
||||
class FrameToolbar(Wrapped):
|
||||
"""The reddit voting toolbar used together with Frame."""
|
||||
extension_handling = False
|
||||
def __init__(self, link = None, **kw):
|
||||
self.title = link.title
|
||||
Wrapped.__init__(self, link = link, *kw)
|
||||
|
||||
def __init__(self, link = None, title = None, url = None, expanded = False, **kw):
|
||||
self.title = title
|
||||
self.url = url
|
||||
self.expanded = expanded
|
||||
self.link = link
|
||||
|
||||
self.dorks = dorks_re.match(link.url if link else url)
|
||||
|
||||
if link:
|
||||
self.tblink = add_sr("/tb/"+link._id36)
|
||||
|
||||
likes = link.likes
|
||||
self.upstyle = "mod" if likes else ""
|
||||
self.downstyle = "mod" if likes is False else ""
|
||||
if c.user_is_loggedin:
|
||||
self.vh = vote_hash(c.user, link, 'valid')
|
||||
score = link.score
|
||||
|
||||
if not link.num_comments:
|
||||
# generates "comment" the imperative verb
|
||||
self.com_label = _("comment {verb}")
|
||||
else:
|
||||
# generates "XX comments" as a noun
|
||||
com_label = ungettext("comment", "comments", link.num_comments)
|
||||
self.com_label = strings.number_label % (link.num_comments, com_label)
|
||||
|
||||
# generates "XX points" as a noun
|
||||
self.score_label = Score.safepoints(score)
|
||||
|
||||
else:
|
||||
self.tblink = add_sr("/s/"+quote(url))
|
||||
submit_url_options = dict(url = _force_unicode(url),
|
||||
then = 'tb')
|
||||
if title:
|
||||
submit_url_options['title'] = _force_unicode(title)
|
||||
self.submit_url = add_sr('/submit' + query_string(submit_url_options))
|
||||
|
||||
if not c.user_is_loggedin:
|
||||
self.loginurl = add_sr("/login?dest="+quote(self.tblink))
|
||||
|
||||
Wrapped.__init__(self, **kw)
|
||||
|
||||
|
||||
class NewLink(Wrapped):
|
||||
"""Render the link submission form"""
|
||||
def __init__(self, captcha = None, url = '', title= '', subreddits = ()):
|
||||
def __init__(self, captcha = None, url = '', title= '', subreddits = (),
|
||||
then = 'comments'):
|
||||
Wrapped.__init__(self, captcha = captcha, url = url,
|
||||
title = title, subreddits = subreddits)
|
||||
title = title, subreddits = subreddits,
|
||||
then = then)
|
||||
|
||||
class ShareLink(Wrapped):
|
||||
def __init__(self, link_name = "", emails = None):
|
||||
@@ -994,7 +1060,13 @@ class Socialite(Wrapped):
|
||||
|
||||
class Bookmarklets(Wrapped):
|
||||
"""The bookmarklets page."""
|
||||
def __init__(self, buttons=["reddit", "serendipity!"]):
|
||||
def __init__(self, buttons=None):
|
||||
if buttons is None:
|
||||
buttons = ["submit", "serendipity!"]
|
||||
# only include the toolbar link if we're not on an
|
||||
# unathorised cname. See toolbar.py:GET_s for discussion
|
||||
if not (c.cname and c.site.domain not in g.authorized_cnames):
|
||||
buttons.insert(0, "reddit toolbar")
|
||||
Wrapped.__init__(self, buttons = buttons)
|
||||
|
||||
|
||||
@@ -1377,4 +1449,6 @@ class RedditTraffic(Traffic):
|
||||
"%5.2f%%" % f))
|
||||
return res
|
||||
|
||||
|
||||
class InnerToolbarFrame(Wrapped):
|
||||
def __init__(self, link, expanded = False):
|
||||
Wrapped.__init__(self, link = link, expanded = expanded)
|
||||
|
||||
@@ -196,9 +196,15 @@ def dockletStr(context, type, browser):
|
||||
|
||||
if type == "serendipity!":
|
||||
return "http://"+site_domain+"/random"
|
||||
elif type == "reddit":
|
||||
return "javascript:location.href='http://"+site_domain+"/submit?url='+encodeURIComponent(location.href)+'&title='+encodeURIComponent(document.title)"
|
||||
elif type == "submit":
|
||||
return ("javascript:location.href='http://"+site_domain+
|
||||
"/submit?url='+encodeURIComponent(location.href)+'&title='+encodeURIComponent(document.title)")
|
||||
elif type == "reddit toolbar":
|
||||
return ("javascript:%20var%20h%20=%20window.location.href;%20h%20=%20'http://" +
|
||||
site_domain + "/s/'%20+%20escape(h);%20window.location%20=%20h;")
|
||||
else:
|
||||
# these are the linked/disliked buttons, which we have removed
|
||||
# from the UI
|
||||
return (("javascript:function b(){var u=encodeURIComponent(location.href);"
|
||||
"var i=document.getElementById('redstat')||document.createElement('a');"
|
||||
"var s=i.style;s.position='%(position)s';s.top='0';s.left='0';"
|
||||
@@ -283,3 +289,7 @@ def choose_width(link, width):
|
||||
return 100 + (10 * (len(str(link._ups - link._downs))))
|
||||
else:
|
||||
return 110
|
||||
|
||||
def panel_size(state):
|
||||
"the frame.cols of the reddit-toolbar's inner frame"
|
||||
return '100%, 400px' if state =='expanded' else '100%x, 0px'
|
||||
|
||||
@@ -26,6 +26,7 @@ import Queue
|
||||
from copy import deepcopy
|
||||
import cPickle as pickle
|
||||
import re, datetime, math, random, string, sha, os
|
||||
from operator import attrgetter
|
||||
|
||||
from datetime import datetime, timedelta
|
||||
from pylons.i18n import ungettext, _
|
||||
@@ -1037,3 +1038,47 @@ def interleave_lists(*args):
|
||||
for a in args:
|
||||
if i < len(a):
|
||||
yield a[i]
|
||||
|
||||
def link_from_url(path, filter_spam = False, multiple = True):
|
||||
from pylons import c
|
||||
from r2.models import IDBuilder, Link, Subreddit, NotFound
|
||||
|
||||
if not path:
|
||||
return
|
||||
|
||||
try:
|
||||
links = Link._by_url(path, c.site)
|
||||
except NotFound:
|
||||
return [] if multiple else None
|
||||
|
||||
links = tup(links)
|
||||
|
||||
# run the list through a builder to remove any that the user
|
||||
# isn't allowed to see
|
||||
links = IDBuilder([link._fullname for link in links],
|
||||
skip = False).get_items()[0]
|
||||
if not links:
|
||||
return
|
||||
|
||||
if filter_spam:
|
||||
# first, try to remove any spam
|
||||
links_nonspam = [ link for link in links
|
||||
if not link._spam ]
|
||||
if links_nonspam:
|
||||
links = links_nonspam
|
||||
|
||||
# if it occurs in one or more of their subscriptions, show them
|
||||
# that one first
|
||||
subs = set(Subreddit.user_subreddits(c.user, limit = None))
|
||||
def cmp_links(a, b):
|
||||
if a.sr_id in subs and b.sr_id not in subs:
|
||||
return -1
|
||||
elif a.sr_id not in subs and b.sr_id in subs:
|
||||
return 1
|
||||
else:
|
||||
return cmp(a._hot, b._hot)
|
||||
links = sorted(links, cmp = cmp_links)
|
||||
|
||||
# among those, show them the hottest one
|
||||
return links if multiple else links[0]
|
||||
|
||||
|
||||
@@ -39,6 +39,7 @@ class Account(Thing):
|
||||
_int_prop_suffix = '_karma'
|
||||
_defaults = dict(pref_numsites = 25,
|
||||
pref_frame = False,
|
||||
pref_frame_commentspanel = True,
|
||||
pref_newwindow = False,
|
||||
pref_public_votes = False,
|
||||
pref_hide_ups = False,
|
||||
|
||||
@@ -400,11 +400,16 @@ class SearchBuilder(QueryBuilder):
|
||||
return done, new_items
|
||||
|
||||
class CommentBuilder(Builder):
|
||||
def __init__(self, link, sort, comment = None, context = None):
|
||||
Builder.__init__(self)
|
||||
def __init__(self, link, sort, comment = None, context = None,
|
||||
load_more=True, continue_this_thread=True,
|
||||
max_depth = MAX_RECURSION, **kw):
|
||||
Builder.__init__(self, **kw)
|
||||
self.link = link
|
||||
self.comment = comment
|
||||
self.context = context
|
||||
self.load_more = load_more
|
||||
self.max_depth = max_depth
|
||||
self.continue_this_thread = continue_this_thread
|
||||
|
||||
if sort.col == '_date':
|
||||
self.sort_key = lambda x: x._date
|
||||
@@ -419,7 +424,7 @@ class CommentBuilder(Builder):
|
||||
for j in self.item_iter(i.child.things):
|
||||
yield j
|
||||
|
||||
def get_items(self, num, nested = True, starting_depth = 0):
|
||||
def get_items(self, num, starting_depth = 0):
|
||||
r = link_comments(self.link._id)
|
||||
cids, comment_tree, depth, num_children = r
|
||||
if cids:
|
||||
@@ -496,14 +501,14 @@ class CommentBuilder(Builder):
|
||||
comments.remove(to_add)
|
||||
if to_add._deleted and not comment_tree.has_key(to_add._id):
|
||||
pass
|
||||
elif depth[to_add._id] < MAX_RECURSION:
|
||||
elif depth[to_add._id] < self.max_depth:
|
||||
#add children
|
||||
if comment_tree.has_key(to_add._id):
|
||||
candidates.extend(comment_tree[to_add._id])
|
||||
sort_candidates()
|
||||
items.append(to_add)
|
||||
num_have += 1
|
||||
else:
|
||||
elif self.continue_this_thread:
|
||||
#add the recursion limit
|
||||
p_id = to_add.parent_id
|
||||
w = Wrapped(MoreRecursion(self.link, 0,
|
||||
@@ -541,6 +546,9 @@ class CommentBuilder(Builder):
|
||||
parent.child = empty_listing(morelink)
|
||||
parent.child.parent_name = parent._fullname
|
||||
|
||||
if not self.load_more:
|
||||
return final
|
||||
|
||||
#put the remaining comments into the tree (the show more comments link)
|
||||
more_comments = {}
|
||||
while candidates:
|
||||
@@ -587,3 +595,16 @@ class CommentBuilder(Builder):
|
||||
mc2.count += 1
|
||||
|
||||
return final
|
||||
|
||||
class TopCommentBuilder(CommentBuilder):
|
||||
"""A comment builder to fetch only the top-level, non-spam,
|
||||
non-deleted comments"""
|
||||
def __init__(self, link, sort, wrap = Wrapped):
|
||||
CommentBuilder.__init__(self, link, sort,
|
||||
load_more = False,
|
||||
continue_this_thread = False,
|
||||
max_depth = 1, wrap = wrap)
|
||||
|
||||
def get_items(self, num = 10):
|
||||
final = CommentBuilder.get_items(self, num = num, starting_depth = 0)
|
||||
return [ cm for cm in final if not cm.deleted ]
|
||||
|
||||
@@ -328,7 +328,17 @@ class Link(Thing, Printable):
|
||||
item.domain_path = "/domain/%s" % item.domain
|
||||
if item.is_self:
|
||||
item.domain_path = item.subreddit_path
|
||||
|
||||
|
||||
item.tblink = "http://%s/tb/%s" % (
|
||||
get_domain(cname = c.cname, subreddit=False),
|
||||
item._id36)
|
||||
|
||||
item.click_url = item.url
|
||||
if item.is_self:
|
||||
item.click_url = item.permalink
|
||||
elif c.user.pref_frame:
|
||||
item.click_url = item.tblink
|
||||
|
||||
if c.user_is_loggedin:
|
||||
incr_counts(wrapped)
|
||||
|
||||
@@ -461,13 +471,16 @@ class Comment(Thing, Printable):
|
||||
wrapped.likes,
|
||||
wrapped.friend,
|
||||
wrapped.collapsed,
|
||||
wrapped.moderator_banned,
|
||||
wrapped.nofollow,
|
||||
wrapped.show_spam,
|
||||
wrapped.show_reports,
|
||||
wrapped.target,
|
||||
wrapped.can_ban,
|
||||
wrapped.moderator_banned,
|
||||
wrapped.can_reply,
|
||||
wrapped.deleted))
|
||||
wrapped.deleted,
|
||||
wrapped.render_class,
|
||||
))
|
||||
s = ''.join(s)
|
||||
return s
|
||||
|
||||
@@ -481,8 +494,8 @@ class Comment(Thing, Printable):
|
||||
@classmethod
|
||||
def add_props(cls, user, wrapped):
|
||||
#fetch parent links
|
||||
links = Link._byID(set(l.link_id for l in wrapped), True)
|
||||
|
||||
links = Link._byID(set(l.link_id for l in wrapped), data = True,
|
||||
return_dict = True)
|
||||
|
||||
#get srs for comments that don't have them (old comments)
|
||||
for cm in wrapped:
|
||||
@@ -499,8 +512,11 @@ class Comment(Thing, Printable):
|
||||
|
||||
for item in wrapped:
|
||||
item.link = links.get(item.link_id)
|
||||
|
||||
if not hasattr(item, 'subreddit'):
|
||||
item.subreddit = item.subreddit_slow
|
||||
if not hasattr(item, 'target'):
|
||||
item.target = None
|
||||
if hasattr(item, 'parent_id'):
|
||||
if cids.has_key(item.parent_id):
|
||||
item.parent_permalink = '#' + utils.to36(item.parent_id)
|
||||
@@ -542,6 +558,11 @@ class Comment(Thing, Printable):
|
||||
item.score_fmt = Score.points
|
||||
item.permalink = item.make_permalink(item.link, item.subreddit)
|
||||
|
||||
class StarkComment(Comment):
|
||||
"""Render class for the comments in the top-comments display in
|
||||
the reddit toolbar"""
|
||||
_nodb = True
|
||||
|
||||
class MoreComments(object):
|
||||
show_spam = False
|
||||
show_reports = False
|
||||
|
||||
@@ -114,7 +114,6 @@ class NestedListing(Listing):
|
||||
def __init__(self, *a, **kw):
|
||||
Listing.__init__(self, *a, **kw)
|
||||
|
||||
self.nested = kw.get('nested', True)
|
||||
self.num = kw.get('num', g.num_comments)
|
||||
self.parent_name = kw.get('parent_name')
|
||||
|
||||
@@ -122,7 +121,7 @@ class NestedListing(Listing):
|
||||
##TODO use the local builder with the render cache. this may
|
||||
##require separating the builder's get_items and tree-building
|
||||
##functionality
|
||||
wrapped_items = self.get_items(num = self.num, nested = True)
|
||||
wrapped_items = self.get_items(num = self.num)
|
||||
|
||||
self.things = wrapped_items
|
||||
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
################################################################################
|
||||
from r2.models import *
|
||||
from r2.lib import promote
|
||||
from r2.lib.utils import fetch_things2
|
||||
|
||||
import string
|
||||
import random
|
||||
@@ -64,3 +65,12 @@ def create_links(num):
|
||||
if random.choice(([False] * 50) + [True]):
|
||||
promote.promote(l)
|
||||
|
||||
|
||||
def by_url_cache():
|
||||
q = Link._query(Link.c._spam == (True,False),
|
||||
data = True,
|
||||
sort = desc('_date'))
|
||||
for i, link in enumerate(fetch_things2(q)):
|
||||
if i % 100 == 0:
|
||||
print "%s..." % i
|
||||
link.set_url_cache()
|
||||
|
||||
BIN
r2/r2/public/static/aminidowngray.gif
Executable file
|
After Width: | Height: | Size: 187 B |
BIN
r2/r2/public/static/aminidownmod.gif
Executable file
|
After Width: | Height: | Size: 126 B |
BIN
r2/r2/public/static/aminiupgray.gif
Executable file
|
After Width: | Height: | Size: 187 B |
BIN
r2/r2/public/static/aminiupmod.gif
Executable file
|
After Width: | Height: | Size: 127 B |
BIN
r2/r2/public/static/button-normal.png
Normal file
|
After Width: | Height: | Size: 220 B |
BIN
r2/r2/public/static/button-pressed.png
Normal file
|
After Width: | Height: | Size: 218 B |
4
r2/r2/public/static/css/reddit-ie7-hax.css
Normal file
@@ -0,0 +1,4 @@
|
||||
.toolbar .middle-side input[type=text] {
|
||||
border: none;
|
||||
height: 17px;
|
||||
}
|
||||
@@ -1,3 +1,7 @@
|
||||
html {
|
||||
height: 100%; /* Needed for toolbar's comments panel's pinstripe */
|
||||
}
|
||||
|
||||
body,div,dl,dt,dd,ul,ol,li,h1,h2,h3,h4,h5,h6,pre,form,fieldset,input,p,blockquote,th,td,iframe {
|
||||
margin:0;
|
||||
padding:0;
|
||||
@@ -19,8 +23,6 @@ body {
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
/*html,body { height: 100%; }*/
|
||||
|
||||
/* IE dumbness patch. hidden input in a hidden block that is
|
||||
* subsequently shown leads to the input to "show" and generate undesired
|
||||
* )padding. This makes it go away. */
|
||||
@@ -725,6 +727,10 @@ a.star { text-decoration: none; color: #ff8b60 }
|
||||
font-size: medium;
|
||||
text-align: right;
|
||||
}
|
||||
.linkcompressed .arrow.down, .linkcompressed .arrow.downmod {
|
||||
margin-top: 2px;
|
||||
}
|
||||
|
||||
.linkcompressed .tagline { display: inline; margin-top: 0px; margin-bottom: 1px; }
|
||||
.linkcompressed .flat-list { display: inline }
|
||||
|
||||
@@ -733,7 +739,7 @@ a.star { text-decoration: none; color: #ff8b60 }
|
||||
.linkcompressed .entry .buttons li.first {padding-left: .5em;}
|
||||
.linkcompressed .entry .buttons li a {
|
||||
padding: 0 2px;
|
||||
background-color: #f6f6f6;
|
||||
background-color: #f7f7f7;
|
||||
font-weight: bold
|
||||
}
|
||||
|
||||
@@ -882,6 +888,20 @@ textarea.gray { color: gray; }
|
||||
padding-left: 5px;
|
||||
}
|
||||
|
||||
.starkcomment + .clearleft + .starkcomment {
|
||||
margin-top: 10px
|
||||
}
|
||||
.starkcomment .commentbox {
|
||||
color: black;
|
||||
background-color: #f0f0f0;
|
||||
padding: 5px;
|
||||
margin-left: 10px;
|
||||
margin-right: 5px;
|
||||
}
|
||||
.starkcomment .tagline {
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
.fixedwidth { float: left; width: 100px; height: 0px; }
|
||||
.clearleft { clear: left; height: 0px; }
|
||||
.clear { clear: both; }
|
||||
@@ -1246,7 +1266,9 @@ textarea.gray { color: gray; }
|
||||
padding-right: 5px;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.details td {
|
||||
vertical-align: top;
|
||||
}
|
||||
.bottommenu { color: gray; font-size: smaller; clear: both}
|
||||
.bottommenu a { color: gray; text-decoration: underline; }
|
||||
|
||||
@@ -1407,18 +1429,154 @@ textarea.gray { color: gray; }
|
||||
font-size: larger;
|
||||
}
|
||||
|
||||
/* the toolbar */
|
||||
.toolbar { height: 30px; border-bottom: 1px solid black;}
|
||||
.toolbar td { vertical-align: center; }
|
||||
.toolbar td#frame-left > a,
|
||||
.toolbar td#frame-left > form { margin-right: 20px; }
|
||||
.toolbar td#frame-right { text-align: right; }
|
||||
.toolbar td#frame-right > a,
|
||||
.toolbar td#frame-right > form { margin: 0 5px; }
|
||||
.toolbar .arrow {
|
||||
background-position: center left;
|
||||
padding-left: 18px;
|
||||
display: inline;
|
||||
.bookmarklet {
|
||||
border: solid #888888 1px;
|
||||
padding: 0px 2px;
|
||||
}
|
||||
|
||||
.toolbar {
|
||||
font-size: small;
|
||||
border-bottom: 1px solid #336699;
|
||||
background-color: #CEE3F8;
|
||||
}
|
||||
|
||||
.toolbar .left-side {
|
||||
height: 19px;
|
||||
float: left;
|
||||
border-right: solid #336699 1px;
|
||||
background-image: url(/static/button-normal.png);
|
||||
}
|
||||
|
||||
.toolbar .middle-side {
|
||||
text-align: center;
|
||||
background-image: url(/static/button-normal.png);
|
||||
}
|
||||
|
||||
.toolbar .middle-side a, .toolbar .middle-side b {
|
||||
display: block;
|
||||
border-left: none;
|
||||
}
|
||||
|
||||
.toolbar .middle-side input[type=text] {
|
||||
font-size: 14px;
|
||||
vertical-align: baseline;
|
||||
width: 100%;
|
||||
height: 18px;
|
||||
border: none;
|
||||
border-top: solid transparent 1px;
|
||||
}
|
||||
.toolbar .middle-side .url {
|
||||
overflow: hidden;
|
||||
}
|
||||
.toolbar .right-side {
|
||||
float: right;
|
||||
background-image: url(/static/button-normal.png);
|
||||
}
|
||||
|
||||
.toolbar a, .toolbar b {
|
||||
font-weight: normal;
|
||||
display: inline-block;
|
||||
height: 18px;
|
||||
border-left: solid #336699 1px;
|
||||
white-space: nowrap;
|
||||
padding: 1px 4px 0px;
|
||||
overflow: hidden;
|
||||
outline: none;
|
||||
-moz-outline: none;
|
||||
}
|
||||
|
||||
.toolbar a, .toolbar .clickable {
|
||||
cursor: pointer;
|
||||
color: #336699;
|
||||
text-decoration: none !important;
|
||||
}
|
||||
|
||||
.toolbar .clickable:active, .pushed-button {
|
||||
background-image: url(/static/button-pressed.png) !important;
|
||||
color: orangered !important;
|
||||
}
|
||||
|
||||
.toolbar a img, toolbar b img {
|
||||
vertical-align: middle;
|
||||
padding-top: 3px;
|
||||
}
|
||||
|
||||
.toolbar .content {
|
||||
float: left;
|
||||
vertical-align: middle;
|
||||
}
|
||||
.toolbar .logo {
|
||||
margin: 0px;
|
||||
padding: 0 2px;
|
||||
border-left: none;
|
||||
vertical-align: top;
|
||||
}
|
||||
.toolbar .title {
|
||||
padding-left: 20px;
|
||||
color: black;
|
||||
font-style: italic;
|
||||
}
|
||||
.toolbar .controls {
|
||||
float: right;
|
||||
}
|
||||
.toolbar .arrow {
|
||||
display: inline-block;
|
||||
width: auto;
|
||||
margin: 0px;
|
||||
background-position: left center;
|
||||
padding-left: 18px;
|
||||
}
|
||||
|
||||
.toolbar .arrow.upmod { background-image: url(/static/aminiupmod.gif); }
|
||||
.toolbar .arrow.downmod { background-image: url(/static/aminidownmod.gif); }
|
||||
.toolbar .arrow.up { background-image: url(/static/aminiupgray.gif); }
|
||||
.toolbar .arrow.down { background-image: url(/static/aminidowngray.gif); }
|
||||
|
||||
.toolbar-status-bar {
|
||||
border-top: solid #336699 1px;
|
||||
border-bottom: solid #336699 1px;
|
||||
background-color: #F6E69F;
|
||||
padding: 0px 2px;
|
||||
overflow: auto;
|
||||
}
|
||||
.toolbar-status-bar .login-arrow-left {
|
||||
overflow: auto;
|
||||
background-image: url(/static/tb-loginarrow-left.png);
|
||||
background-position: top right;
|
||||
}
|
||||
.toolbar-status-bar .login-arrow-right {
|
||||
float: right;
|
||||
margin-right: 75px;
|
||||
}
|
||||
.toolbar-status-bar .login-message {
|
||||
float: left;
|
||||
background-color: #F6E69F;
|
||||
padding-right: 3px;
|
||||
}
|
||||
.tb-comments-panel-toggle {
|
||||
display: block;
|
||||
font-size: larger;
|
||||
margin: 15px 13px;
|
||||
}
|
||||
.min-body {
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.min-body .content {
|
||||
margin-top: 0px;
|
||||
border-left: solid #369 1px;
|
||||
min-height: 100%;
|
||||
max-width: 60em;
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
.min-body .content h1, .min-body .content h2 {
|
||||
padding-left: 13px;
|
||||
display: inline-block;
|
||||
margin-bottom: 15px;
|
||||
}
|
||||
.min-body .content #noresults {
|
||||
margin: 0 0 0 13px;
|
||||
}
|
||||
|
||||
/* default form styles */
|
||||
|
||||
BIN
r2/r2/public/static/dorks-toolbar.png
Normal file
|
After Width: | Height: | Size: 504 B |
|
Before Width: | Height: | Size: 20 KiB After Width: | Height: | Size: 8.8 KiB |
BIN
r2/r2/public/static/help/tb-ss-close.png
Normal file
|
After Width: | Height: | Size: 357 B |
BIN
r2/r2/public/static/help/tb-ss-comment.png
Normal file
|
After Width: | Height: | Size: 1.0 KiB |
BIN
r2/r2/public/static/help/tb-ss-help.png
Normal file
|
After Width: | Height: | Size: 344 B |
BIN
r2/r2/public/static/help/tb-ss-left.png
Normal file
|
After Width: | Height: | Size: 3.4 KiB |
BIN
r2/r2/public/static/help/tb-ss-link.png
Normal file
|
After Width: | Height: | Size: 358 B |
BIN
r2/r2/public/static/help/tb-ss-logo.png
Normal file
|
After Width: | Height: | Size: 722 B |
BIN
r2/r2/public/static/help/tb-ss-logout.png
Normal file
|
After Width: | Height: | Size: 906 B |
BIN
r2/r2/public/static/help/tb-ss-middle.png
Normal file
|
After Width: | Height: | Size: 1.9 KiB |
BIN
r2/r2/public/static/help/tb-ss-right.png
Normal file
|
After Width: | Height: | Size: 2.5 KiB |
BIN
r2/r2/public/static/help/tb-ss-scoreetc.png
Normal file
|
After Width: | Height: | Size: 2.3 KiB |
BIN
r2/r2/public/static/help/tb-ss-serendipity.png
Normal file
|
After Width: | Height: | Size: 1.4 KiB |
BIN
r2/r2/public/static/help/tb-ss-username.png
Normal file
|
After Width: | Height: | Size: 744 B |
BIN
r2/r2/public/static/help/tb-ss-whole.png
Normal file
|
After Width: | Height: | Size: 6.0 KiB |
|
Before Width: | Height: | Size: 24 KiB After Width: | Height: | Size: 7.9 KiB |
@@ -33,7 +33,16 @@ $.redirect = function(dest) {
|
||||
$.fn.redirect = function(dest) {
|
||||
/* for forms which are "posting" by ajax leading to a redirect */
|
||||
$(this).filter("form").find(".status").show().html("redirecting...");
|
||||
$.redirect(dest);
|
||||
var target = $(this).attr('target');
|
||||
if(target == "_top") {
|
||||
var w = window;
|
||||
while(w != w.parent) {
|
||||
w = w.parent;
|
||||
}
|
||||
w.location = dest;
|
||||
} else {
|
||||
$.redirect(dest);
|
||||
}
|
||||
/* this should never happen, but for the sake of internal consistency */
|
||||
return $(this)
|
||||
}
|
||||
|
||||
@@ -621,6 +621,118 @@ function register(elem) {
|
||||
return post_user(this, "register");
|
||||
};
|
||||
|
||||
var toolbar_p = function(expanded_size, collapsed_size) {
|
||||
/* namespace for functions related to the reddit toolbar frame */
|
||||
|
||||
this.toggle_linktitle = function(s) {
|
||||
$('.title, .submit, .url').toggle();
|
||||
if($(s).is('.pushed-button')) {
|
||||
$(s).parents('.middle-side').removeClass('clickable');
|
||||
} else {
|
||||
$(s).parents('.middle-side').addClass('clickable');
|
||||
}
|
||||
return this.toggle_pushed(s);
|
||||
};
|
||||
|
||||
this.toggle_pushed = function(s) {
|
||||
s = $(s);
|
||||
if(s.is('.pushed-button')) {
|
||||
s.removeClass('pushed-button').addClass('popped-button');
|
||||
} else {
|
||||
s.removeClass('popped-button').addClass('pushed-button');
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
this.push_button = function(s) {
|
||||
$(s).removeClass("popped-button").addClass("pushed-button");
|
||||
};
|
||||
|
||||
this.pop_button = function(s) {
|
||||
$(s).removeClass("pushed-button").addClass("popped-button");
|
||||
};
|
||||
|
||||
this.serendipity = function() {
|
||||
this.push_button('.serendipity');
|
||||
return true;
|
||||
};
|
||||
|
||||
this.show_panel = function() {
|
||||
parent.inner_toolbar.document.body.cols = expanded_size;
|
||||
};
|
||||
|
||||
this.hide_panel = function() {
|
||||
parent.inner_toolbar.document.body.cols = collapsed_size;
|
||||
};
|
||||
|
||||
this.resize_toolbar = function() {
|
||||
var height = $("body").height();
|
||||
parent.document.body.rows = height + "px, 100%";
|
||||
};
|
||||
|
||||
this.login_msg = function() {
|
||||
$(".toolbar-status-bar").show();
|
||||
$(".login-arrow").show();
|
||||
this.resize_toolbar();
|
||||
return false;
|
||||
};
|
||||
|
||||
this.top_window = function() {
|
||||
var w = window;
|
||||
while(w != w.parent) {
|
||||
w = w.parent;
|
||||
}
|
||||
return w.parent;
|
||||
};
|
||||
|
||||
var pop_obj = null;
|
||||
this.panel_loadurl = function(url) {
|
||||
try {
|
||||
var cur = window.parent.inner_toolbar.reddit_panel.location;
|
||||
if (cur == url) {
|
||||
return false;
|
||||
} else {
|
||||
if (pop_obj != null) {
|
||||
this.pop_button(pop_obj);
|
||||
pop_obj = null;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
} catch (e) {
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
var comments_on = 0;
|
||||
this.comments_pushed = function(ctl) {
|
||||
comments_on = ! comments_on;
|
||||
|
||||
if (comments_on) {
|
||||
this.push_button(ctl);
|
||||
this.show_panel();
|
||||
} else {
|
||||
this.pop_button(ctl);
|
||||
this.hide_panel();
|
||||
}
|
||||
};
|
||||
|
||||
this.gourl = function(form, base_url) {
|
||||
var url = $(form).find('input[type=text]').attr('value');
|
||||
var newurl = base_url + escape(url);
|
||||
|
||||
this.top_window().location.href = newurl;
|
||||
|
||||
return false;
|
||||
};
|
||||
|
||||
this.pref_commentspanel_hide = function() {
|
||||
$.request('tb_commentspanel_hide');
|
||||
};
|
||||
this.pref_commentspanel_show = function() {
|
||||
$.request('tb_commentspanel_show');
|
||||
};
|
||||
};
|
||||
|
||||
/* The ready method */
|
||||
$(function() {
|
||||
/* set function to be called on thing creation/replacement,
|
||||
|
||||
BIN
r2/r2/public/static/link.png
Normal file
|
After Width: | Height: | Size: 198 B |
BIN
r2/r2/public/static/logo-toolbar.png
Normal file
|
After Width: | Height: | Size: 582 B |
|
Before Width: | Height: | Size: 28 KiB After Width: | Height: | Size: 12 KiB |
BIN
r2/r2/public/static/tb-loginarrow-left.png
Normal file
|
After Width: | Height: | Size: 168 B |
BIN
r2/r2/public/static/tb-loginarrow-right.png
Normal file
|
After Width: | Height: | Size: 181 B |
@@ -24,37 +24,37 @@
|
||||
|
||||
<div class="instructions">
|
||||
<script type="text/javascript">
|
||||
function dragme() {window.alert("drag this link to your toolbar")};function favme() {window.alert('right-click this link and choose "Add to Favorites"')}
|
||||
function dragme() {window.alert("drag this link to your bookmark bar")};function favme() {window.alert('right-click this link and choose "Add to Favorites"')}
|
||||
</script>
|
||||
<h1>
|
||||
${_("install the %(site)s bookmarklet set") % dict(site=c.site.name)}
|
||||
</h1>
|
||||
<p>${_("once added to your toolbar, these buttons will let you \"reddit this\" (submit the link, or if it's already been submitted, share it and/or comment on it), like, dislike, and save links while you surf.")}</p>
|
||||
<p>${_("once added to your bookmark bar, you can click these buttons from any site to get quick access to reddit functionality.")}</p>
|
||||
<h2>${_("in Firefox")}</h2>
|
||||
<p>
|
||||
Try out our new firefox add-on,  <a href="/socialite">Socialite</a>.
|
||||
</p>
|
||||
<p>
|
||||
or ${_("click and drag")}
|
||||
${_("click and drag")}
|
||||
%for type in thing.buttons:
|
||||
<a style="padding: 0 3px 0 3px" href="${dockletStr(type, 'firefox')}" onclick="dragme(); return false">
|
||||
<img alt="${type}" src="/static/${type}_firefox.png" />
|
||||
<span class="bookmarklet">${type}</span>
|
||||
</a>
|
||||
%endfor
|
||||
${_("to your toolbar.")}
|
||||
${_("to your bookmark bar.")}
|
||||
</p>
|
||||
<p>
|
||||
<img border="0" src="/static/firefox.png" alt="firefox screenshot" />
|
||||
</p>
|
||||
<p>
|
||||
See also our Firefox add-on,  <a href="/socialite">Socialite</a>.
|
||||
</p>
|
||||
<h2>${_("in Internet Explorer")}</h2>
|
||||
<p>
|
||||
${_("right-click on")}
|
||||
%for type in thing.buttons:
|
||||
<a style="padding: 0 3px 0 3px" href="${dockletStr(type, 'ie')|}" onclick="favme(); return false">
|
||||
<img alt="${type}" src="/static/${type}_ie.png" />
|
||||
<span class="bookmarklet">${type}</span>
|
||||
</a>
|
||||
%endfor
|
||||
${_('choose "Add to Favorites" and add to the "Links" folder.')}
|
||||
${_('then choose "Add to Favorites" and add to the "Links" folder.')}
|
||||
</p>
|
||||
<p>
|
||||
<img border="0" src="/static/ie.png" alt="ie screenshot" />
|
||||
@@ -64,10 +64,10 @@
|
||||
${_("click and drag")}
|
||||
%for type in thing.buttons:
|
||||
<a style="padding: 0 3px 0 3px" href="${dockletStr(type, 'safari')}" onclick="dragme(); return false">
|
||||
<img alt="${type}" src="/static/${type}_safari.png" />
|
||||
<span class="bookmarklet">${type}</span>
|
||||
</a>
|
||||
%endfor
|
||||
${_("to your toolbar.")}
|
||||
${_("to your bookmark bar.")}
|
||||
</p>
|
||||
<p>
|
||||
<img border="0" src="/static/safari.png" alt="safari screenshot"/>
|
||||
|
||||
@@ -52,7 +52,7 @@ ${class_def(1, width=choose_width(thing.link, thing.width))}
|
||||
%if thing.vote:
|
||||
${arrow(thing.link, 1, thing.likes)}
|
||||
${arrow(thing.link, 0, thing.likes == False)}
|
||||
${score(thing.link, thing.likes, inline=False)}
|
||||
${score(thing.link, thing.likes, tag='div')}
|
||||
%else:
|
||||
${thing.link.score}
|
||||
%endif
|
||||
@@ -68,7 +68,7 @@ ${class_def(1, width=choose_width(thing.link, thing.width))}
|
||||
%if thing.link:
|
||||
%if thing.vote:
|
||||
${arrow(thing.link, 1, thing.likes)}
|
||||
${score(thing.link, thing.likes, inline=False)}
|
||||
${score(thing.link, thing.likes, tag='div')}
|
||||
${arrow(thing.link, 0, thing.likes == False)}
|
||||
%else:
|
||||
<br />
|
||||
@@ -96,7 +96,7 @@ ${class_def(3)}
|
||||
%if thing.link:
|
||||
%if thing.vote:
|
||||
${arrow(thing.link, 1, thing.likes)}
|
||||
${score(thing.link, thing.likes, inline=False)}
|
||||
${score(thing.link, thing.likes, tag='div')}
|
||||
${arrow(thing.link, 0, thing.likes == False)}
|
||||
%else:
|
||||
<br />
|
||||
@@ -121,7 +121,7 @@ ${class_def(3)}
|
||||
%if thing.link:
|
||||
%if thing.vote:
|
||||
${arrow(thing.link, 1, thing.likes)}
|
||||
${score(thing.link, thing.likes, inline=False)}
|
||||
${score(thing.link, thing.likes, tag='div')}
|
||||
${arrow(thing.link, 0, thing.likes == False)}
|
||||
%else:
|
||||
<br />
|
||||
|
||||
@@ -54,7 +54,7 @@ ${parent.midcol(not thing.collapsed)}
|
||||
${parent.collapsed()}
|
||||
</%def>
|
||||
|
||||
<%def name="tagline(collapse=False)">
|
||||
<%def name="tagline(collapse=False,showexpandcollapse=True)">
|
||||
<%
|
||||
if c.user_is_admin:
|
||||
show = True
|
||||
@@ -76,24 +76,25 @@ ${parent.collapsed()}
|
||||
%if show:
|
||||
${unsafe(self.score(thing, likes = thing.likes))} 
|
||||
%endif
|
||||
${thing.timesince} ${_("ago")}
|
||||
${_("%(timeago)s ago") % dict(timeago=thing.timesince)}
|
||||
%if thing.editted:
|
||||
<em>*</em>
|
||||
%endif
|
||||
%endif
|
||||
<a href="#" class="expand"
|
||||
%if collapse:
|
||||
onclick="return showcomment(this)">
|
||||
%else:
|
||||
onclick="return hidecomment(this)">
|
||||
%endif
|
||||
[${_("+") if collapse else _("-")}]
|
||||
%if collapse:
|
||||
(${thing.num_children}
|
||||
${ungettext("child", "children", thing.num_children)})
|
||||
%if showexpandcollapse:
|
||||
<a href="#" class="expand"
|
||||
%if collapse:
|
||||
onclick="return showcomment(this)">
|
||||
%else:
|
||||
onclick="return hidecomment(this)">
|
||||
%endif
|
||||
[${_("+") if collapse else _("-")}]
|
||||
%if collapse:
|
||||
(${thing.num_children}
|
||||
${ungettext("child", "children", thing.num_children)})
|
||||
%endif
|
||||
</a>
|
||||
%endif
|
||||
</a>
|
||||
|
||||
</%def>
|
||||
|
||||
<%def name="Child()">
|
||||
@@ -102,7 +103,8 @@ ${parent.Child(not thing.collapsed)}
|
||||
|
||||
<%def name="commentBody()">
|
||||
%if c.user_is_admin or not thing.deleted:
|
||||
${unsafe(safemarkdown(thing.body, thing.nofollow))}
|
||||
${unsafe(safemarkdown(thing.body, nofollow=thing.nofollow,
|
||||
target=thing.target))}
|
||||
%else:
|
||||
<div class="gray md">
|
||||
${_("[deleted]")}
|
||||
|
||||
46
r2/r2/templates/commentspanel.html
Normal file
@@ -0,0 +1,46 @@
|
||||
## The contents of this file are subject to the Common Public Attribution
|
||||
## License Version 1.0. (the "License"); you may not use this file except in
|
||||
## compliance with the License. You may obtain a copy of the License at
|
||||
## http://code.reddit.com/LICENSE. The License is based on the Mozilla Public
|
||||
## License Version 1.1, but Sections 14 and 15 have been added to cover use of
|
||||
## software over a computer network and provide for limited attribution for the
|
||||
## Original Developer. In addition, Exhibit A has been modified to be consistent
|
||||
## with Exhibit B.
|
||||
##
|
||||
## Software distributed under the License is distributed on an "AS IS" basis,
|
||||
## WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for
|
||||
## the specific language governing rights and limitations under the License.
|
||||
##
|
||||
## The Original Code is Reddit.
|
||||
##
|
||||
## The Original Developer is the Initial Developer. The Initial Developer of
|
||||
## the Original Code is CondeNet, Inc.
|
||||
##
|
||||
## All portions of the code written by CondeNet are Copyright (c) 2006-2009
|
||||
## CondeNet, Inc. All Rights Reserved.
|
||||
################################################################################
|
||||
|
||||
<%namespace file="printable.html" import="toggle_button"/>
|
||||
|
||||
<script type="text/javascript">
|
||||
toolbar = new toolbar_p();
|
||||
</script>
|
||||
|
||||
<h1>
|
||||
${_('top comments')}
|
||||
</h1>
|
||||
<h2>
|
||||
<a target="_top" href="${thing.link.permalink}">
|
||||
${_("full discussion")}
|
||||
</a>
|
||||
</h2>
|
||||
|
||||
${thing.listing.render()}
|
||||
|
||||
${toggle_button("tb-comments-panel-toggle",
|
||||
_("hide this panel by default"),
|
||||
_("show this panel " +
|
||||
"when there are comments"),
|
||||
"toolbar.pref_commentspanel_hide",
|
||||
"toolbar.pref_commentspanel_show",
|
||||
reverse = not c.user.pref_frame_commentspanel)}
|
||||
@@ -21,6 +21,8 @@
|
||||
################################################################################
|
||||
<%
|
||||
from r2.lib.template_helpers import add_sr
|
||||
from r2.lib.utils import query_string
|
||||
from r2.lib.filters import _force_unicode
|
||||
%>
|
||||
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/html4/frameset.dtd">
|
||||
@@ -28,8 +30,36 @@
|
||||
<head>
|
||||
<title>${thing.title}</title>
|
||||
</head>
|
||||
<frameset framespacing="0" rows="30px, 100%">
|
||||
<frame frameborder="0" scrolling="no" src="${add_sr('/toolbar?id=' + thing.fullname)}"/>
|
||||
<frame frameborder="0" src="${thing.url}"/>
|
||||
<frameset framespacing="0" frameborder="0" border="0" rows="20px, 100%">
|
||||
%if thing.fullname:
|
||||
<frame frameborder="0" border="0" scrolling="no" name="reddit_top"
|
||||
noresize="1" src="${add_sr('/toolbar/toolbar?id=' + thing.fullname)}"
|
||||
/>
|
||||
<frame frameborder="0" border="0"
|
||||
src="${add_sr('/toolbar/inner?id='+thing.fullname)}" name="inner_toolbar" />
|
||||
%else:
|
||||
<frame frameborder="0" border="0" scrolling="no" name="reddit_top"
|
||||
src="${add_sr('/toolbar/toolbar' +
|
||||
query_string(dict(url = thing.url,
|
||||
title = _force_unicode(thing.title))))}"
|
||||
/>
|
||||
<frame frameborder="0" border="0"
|
||||
src="${thing.url}" name="inner_toolbar" />
|
||||
%endif
|
||||
</frameset>
|
||||
|
||||
<!-- Internet Explorer has a "feature" called "friendly error
|
||||
messages" that defaults to being turned on, where it detects
|
||||
certain remote error conditions (among them, 404s) such that
|
||||
the response (presumably an error descriptor page) is less
|
||||
than some size (512 bytes for 404s). If that happens, it
|
||||
replaces the remote error message with a more "friendly"
|
||||
description of the error, which obscures the server's error
|
||||
message. Historically, this is because Apache's and IIS's
|
||||
error messages are famously non-helpful, and were less than
|
||||
that minimum size. This unnecessarily verbose comment serves
|
||||
only to cause this page (whose status code may be a 404, set
|
||||
in toolbar.py:GET_s) to go over that minimum size, so that we
|
||||
can force our content to be shown to IE users with "friendly
|
||||
error messages", even on braindead browsers. -->
|
||||
</html>
|
||||
|
||||
@@ -20,118 +20,164 @@
|
||||
## CondeNet, Inc. All Rights Reserved.
|
||||
################################################################################
|
||||
<%!
|
||||
from r2.lib.template_helpers import static, get_domain
|
||||
from r2.lib.template_helpers import static, get_domain, add_sr, panel_size
|
||||
from r2.lib.strings import Score
|
||||
%>
|
||||
|
||||
<%inherit file="reddit.html"/>
|
||||
<%namespace file="utils.html" import="plain_link, logout"/>
|
||||
<%namespace file="printable.html" import="state_button, comment_button, thing_css_class" />
|
||||
<%namespace file="printable.html" import="state_button, comment_button, thing_css_class, score" />
|
||||
|
||||
<%def name="javascript_run()">
|
||||
${parent.javascript_run()}
|
||||
toolbar = new toolbar_p("${panel_size('expanded')}", "${panel_size('collapsed')}");
|
||||
</%def>
|
||||
|
||||
<%def name="bodyHTML()">
|
||||
<body>
|
||||
<% fullname = thing.link._fullname %>
|
||||
<% upstyle = "mod" if thing.link.likes else "" %>
|
||||
<% downstyle = "mod" if thing.link.likes is False else "" %>
|
||||
<table class="${thing_css_class(thing.link)} toolbar" width="100%">
|
||||
<script type="text/javascript">
|
||||
function kill(uh) {
|
||||
$("#main").hide();
|
||||
$("#killed").show();
|
||||
$.request('noframe');
|
||||
}
|
||||
|
||||
function unkill() {
|
||||
$("#killed").hide();
|
||||
$("#main").show();
|
||||
$.request('frame');
|
||||
}
|
||||
|
||||
</script>
|
||||
<tr id="killed" style="display: none" class="menu">
|
||||
<td nowrap="nowrap">
|
||||
after reloading, this frame will not be shown again. click
|
||||
 <a href="javascript:unkill()"> here</a> to undo.</td>
|
||||
<td width="100%" />
|
||||
</tr>
|
||||
<tr id="main">
|
||||
<td id="frame-left">
|
||||
<a target="_top" href="http://${get_domain(cname = c.cname)}/">
|
||||
<img style="border: none" src="${static('littlehead.png')}"
|
||||
alt="reddit.com" title="reddit.com" />
|
||||
</a>
|
||||
<a id="up_${fullname}" class="arrow up${upstyle}"
|
||||
%if c.user_is_loggedin:
|
||||
href="javascript:void(0);"
|
||||
onclick="$(this).vote()"
|
||||
%else:
|
||||
href="/login"
|
||||
target="_top"
|
||||
%endif
|
||||
>
|
||||
${_("like")}
|
||||
</a>
|
||||
<a id="down_${fullname}" class="arrow down${downstyle}"
|
||||
%if c.user_is_loggedin:
|
||||
href="javascript:void(0);"
|
||||
onclick="$(this).vote()"
|
||||
%else:
|
||||
href="/login"
|
||||
target="_top"
|
||||
%endif
|
||||
>
|
||||
${_("dislike")}
|
||||
</a>
|
||||
%if c.user_is_loggedin:
|
||||
%if thing.link.saved:
|
||||
${state_button("unsave", _("unsave"),
|
||||
"return change_state(this, 'unsave');", _("unsaved"))}
|
||||
%else:
|
||||
${state_button("save", _("save"),
|
||||
"return change_state(this, 'save');", _("saved"))}
|
||||
%endif
|
||||
%endif
|
||||
<%
|
||||
if not thing.link.num_comments:
|
||||
# generates "comment" the imperative verb
|
||||
com_label = _("comment {verb}")
|
||||
else:
|
||||
# generates "XX comments" as a noun
|
||||
com_label = ungettext("comment", "comments", thing.link.num_comments)
|
||||
%>
|
||||
<span>
|
||||
${comment_button("comment", com_label,
|
||||
thing.link.num_comments,
|
||||
thing.link.permalink)}
|
||||
</span>
|
||||
</td>
|
||||
<td id="frame-middle" nowrap="nowrap" style="display: none">
|
||||
</td>
|
||||
<td id="frame-right" class="menu" nowrap="nowrap">
|
||||
%if c.user_is_loggedin:
|
||||
<a href="http://${get_domain(cname = c.cname)}/user/${c.user.name}"
|
||||
target="_parent">${c.user.name}</a> (${c.user.safe_karma})
|
||||
${logout()}
|
||||
%else:
|
||||
<a href="/login">${_("login")}</a>
|
||||
<a href="/login">${_("register")}</a>
|
||||
<body class="toolbar">
|
||||
<div class="left-side">
|
||||
<a class="logo" target="_top" href="http://${get_domain(cname = c.cname)}/">
|
||||
<img src="${static('logo-toolbar.png')}" alt="${c.site.description or c.site.name}"
|
||||
title="${c.site.description or c.site.name}"/>
|
||||
%if thing.dorks:
|
||||
<img src="${static('dorks-toolbar.png')}"
|
||||
title="${_('caution: dorkbar detected')}"/>
|
||||
%endif
|
||||
<a target="_top" href="/help/">
|
||||
<img style="border: none" src="${static('help.png')}"
|
||||
alt="help" title="help" />
|
||||
</a>
|
||||
<a target="_top" href="${thing.link.url}">
|
||||
<img style="border: none"
|
||||
src="${static('breakout.png')}"
|
||||
alt="open without frame" title="open without frame" />
|
||||
</a>
|
||||
<a href="javascript:kill()">
|
||||
<img style="cursor: pointer"
|
||||
src="${static('kill.png')}"
|
||||
alt="permanently close this frame"
|
||||
title="permanently close this frame" />
|
||||
</a>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</a>
|
||||
|
||||
%if thing.link:
|
||||
${withlink()}
|
||||
%endif
|
||||
</div>
|
||||
|
||||
<div class="right-side">
|
||||
<a href="#" onclick="return toolbar.toggle_linktitle(this);">
|
||||
<img src="${static('link.png')}" height="13" width="16"
|
||||
title="${_('show url')}" alt="${_('show url')}"/>
|
||||
</a>
|
||||
|
||||
<a class="serendipity popped-button"
|
||||
title="${_('load a random link')}"
|
||||
onmousedown="toolbar.push_button(this)"
|
||||
onmouseup="toolbar.pop_button(this)"
|
||||
onclick="toolbar.serendipity()"
|
||||
href="${add_sr('/random')}"
|
||||
target="_top" />
|
||||
%if c.default_sr:
|
||||
${_("serendipity")}
|
||||
%else:
|
||||
${"%(subreddit)s serendipity" % dict (subreddit=c.site.name)}
|
||||
%endif
|
||||
</a>
|
||||
|
||||
%if c.user_is_loggedin:
|
||||
<a href="http://${get_domain(cname = c.cname)}/user/${c.user.name}"
|
||||
title="${_('visit your userpage')}"
|
||||
class="clickable" target="_top">${c.user.name}</a>
|
||||
${logout(top=True,dest=thing.tblink,a_class="clickable")}
|
||||
%elif thing.link:
|
||||
<a href="${thing.loginurl}" target="_top" class="clickable">
|
||||
${_("login / register")}
|
||||
</a>
|
||||
%endif
|
||||
|
||||
<a target="_top" href="/help/toolbar">
|
||||
<img src="${static('help.png')}"
|
||||
height="11" width="11"
|
||||
alt="${_('help')}" title="${_('help')}" />
|
||||
</a>
|
||||
|
||||
<a href="${thing.url}" target="_top">
|
||||
<img src="${static('kill.png')}"
|
||||
height="11" width="11"
|
||||
alt="${_('turn off the toolbar')}"
|
||||
title="${_('turn off the toolbar')}" />
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<div class="middle-side clickable">
|
||||
%if thing.link:
|
||||
<a
|
||||
title="${_('click to visit the main page for this submission')}"
|
||||
class="title clickable"
|
||||
target="_top"
|
||||
href="${thing.link.make_permalink_slow()}">
|
||||
${thing.link.title}
|
||||
</a>
|
||||
%else:
|
||||
${plain_link(_('click to submit this link to reddit'), thing.submit_url,
|
||||
target="_top", _class="submit")}
|
||||
%endif
|
||||
<div class="url" style="display: none;">
|
||||
<form onsubmit="return toolbar.gourl(this, '${add_sr('/s/')}')">
|
||||
<input type="text" value="${thing.url}" />
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="toolbar-status-bar" style="display: none;">
|
||||
<div class="login-arrow" style="display: none;">
|
||||
<img src="${static('tb-loginarrow-right.png')}" class="login-arrow-right"/>
|
||||
<div class="login-arrow-left">
|
||||
<p class="login-message">
|
||||
${_("you'll need to login or register to do that")}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</%def>
|
||||
|
||||
|
||||
<%def name="withlink()">
|
||||
<span class="${thing_css_class(thing.link)}">
|
||||
<span>
|
||||
${score(thing.link, thing.link.likes, score_fmt = Score.safepoints, tag='b')}
|
||||
</span>
|
||||
<span class="arrows">
|
||||
<%def name="arrow(direction, style, message)">
|
||||
<a class="arrow ${direction + style}"
|
||||
title="${_('vote %(direction)s') % dict(direction=direction)}"
|
||||
%if c.user_is_loggedin:
|
||||
href="javascript:void(0);"
|
||||
onclick="$(this).vote('${thing.vh}')"
|
||||
%else:
|
||||
href="${thing.loginurl}"
|
||||
target="_top"
|
||||
onclick="return toolbar.login_msg()"
|
||||
%endif
|
||||
>
|
||||
${message}
|
||||
</a>
|
||||
</%def>
|
||||
|
||||
${arrow("up", thing.upstyle, _("like"))}
|
||||
${arrow("down", thing.downstyle, _("dislike"))}
|
||||
</span>
|
||||
|
||||
|
||||
%if c.user_is_loggedin:
|
||||
%if thing.link.saved:
|
||||
${state_button("unsave", _("unsave"),
|
||||
"return change_state(this, 'unsave');", "<b>%s</b>" % _("unsaved"),
|
||||
a_class="clickable")}
|
||||
%else:
|
||||
${state_button("save", _("save"),
|
||||
"return change_state(this, 'save');", "<b>%s</b>" % _("saved"),
|
||||
a_class="clickable")}
|
||||
%endif
|
||||
%endif
|
||||
|
||||
<a href="/toolbar/comments/${thing.link._id36}" target="reddit_panel"
|
||||
title="${_('toggle the comments panel')}"
|
||||
onclick="toolbar.comments_pushed(this); return toolbar.panel_loadurl(this.href);"
|
||||
class="comments comments-button">${thing.com_label}</a>
|
||||
</span>
|
||||
|
||||
%if thing.link and thing.expanded:
|
||||
<script type="text/javascript">
|
||||
$(function() {
|
||||
toolbar.comments_pushed($('.comments-button'));
|
||||
});
|
||||
</script>
|
||||
%endif
|
||||
</%def>
|
||||
|
||||
30
r2/r2/templates/innertoolbarframe.html
Normal file
@@ -0,0 +1,30 @@
|
||||
## The contents of this file are subject to the Common Public Attribution
|
||||
## License Version 1.0. (the "License"); you may not use this file except in
|
||||
## compliance with the License. You may obtain a copy of the License at
|
||||
## http://code.reddit.com/LICENSE. The License is based on the Mozilla Public
|
||||
## License Version 1.1, but Sections 14 and 15 have been added to cover use of
|
||||
## software over a computer network and provide for limited attribution for the
|
||||
## Original Developer. In addition, Exhibit A has been modified to be consistent
|
||||
## with Exhibit B.
|
||||
##
|
||||
## Software distributed under the License is distributed on an "AS IS" basis,
|
||||
## WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for
|
||||
## the specific language governing rights and limitations under the License.
|
||||
##
|
||||
## The Original Code is Reddit.
|
||||
##
|
||||
## The Original Developer is the Initial Developer. The Initial Developer of
|
||||
## the Original Code is CondeNet, Inc.
|
||||
##
|
||||
## All portions of the code written by CondeNet are Copyright (c) 2006-2009
|
||||
## CondeNet, Inc. All Rights Reserved.
|
||||
################################################################################
|
||||
<%!
|
||||
from r2.lib.template_helpers import add_sr, panel_size
|
||||
%>
|
||||
<html>
|
||||
<frameset cols="${panel_size('expanded' if thing.expanded else 'collapsed')}" name="inner_toolbar">
|
||||
<frame frameborder="0" src="${thing.link.url}" name="reddit_link" />
|
||||
<frame frameborder="0" src="${add_sr('/toolbar/comments/'+thing.link._id36)}" name="reddit_panel" />
|
||||
</frameset>
|
||||
</html>
|
||||
@@ -43,19 +43,13 @@
|
||||
</%def>
|
||||
|
||||
<%def name="make_link(name, css_class)">
|
||||
<a class="${css_class} ${ c.user_is_loggedin and 'loggedin' or ''} ${thing.clicked and 'click' or ''}"
|
||||
%if c.user.pref_frame:
|
||||
href="http://${get_domain(cname = c.cname, subreddit = False)}/goto?id=${thing._id36}"
|
||||
%elif thing.is_self:
|
||||
href="${thing.permalink}"
|
||||
%else:
|
||||
href="${thing.url}"
|
||||
%endif
|
||||
<a class="${css_class} ${ c.user_is_loggedin and 'loggedin' or ''} ${thing.clicked and 'click' or ''}"
|
||||
href="${thing.click_url}"
|
||||
%if thing.nofollow:
|
||||
rel="nofollow"
|
||||
%endif
|
||||
%if c.user.pref_newwindow:
|
||||
target="_blank"
|
||||
target="_blank"
|
||||
%elif c.cname:
|
||||
target="_top"
|
||||
%endif
|
||||
@@ -96,7 +90,7 @@
|
||||
%if thing.hide_score:
|
||||
<div class="score">•</div>
|
||||
%else:
|
||||
${self.score(thing, thing.likes, inline=False)}
|
||||
${self.score(thing, thing.likes, tag='div')}
|
||||
%endif
|
||||
${self.arrow(thing, 0, thing.likes == False)}
|
||||
</div>
|
||||
|
||||
@@ -23,6 +23,8 @@
|
||||
|
||||
<div class="raisedbox linkinfo ${thing_css_class(thing.a)}">
|
||||
<table class="details">
|
||||
<tr><th>${_("toolbar link")}</th>
|
||||
<td><a href="${thing.a.tblink}">${thing.a.tblink}</a></td></tr>
|
||||
<tr><th>${_("submitted on")}</th>
|
||||
<td>${thing.a._date.strftime(thing.datefmt)}</td></tr>
|
||||
<tr><th>${ungettext('point', 'points', 5)}</th>
|
||||
|
||||
@@ -22,6 +22,7 @@
|
||||
|
||||
<%!
|
||||
from r2.lib.strings import strings
|
||||
from r2.lib.template_helpers import add_sr
|
||||
%>
|
||||
<%namespace file="utils.html" import="error_field, submit_form, plain_link, text_with_links"/>
|
||||
|
||||
@@ -31,11 +32,12 @@
|
||||
<h1>${_("submit to %(site)s") % dict(site=c.site.name)}</h1>
|
||||
%endif
|
||||
|
||||
<%call expr="submit_form(onsubmit='return post_form(this, \'submit\', linkstatus, null, true)',
|
||||
action='/submit', _class='long-text content', _id='newlink')">
|
||||
<%call expr="submit_form(onsubmit='return post_form(this, \'submit\', linkstatus, null, true)',
|
||||
action=add_sr('/submit'), _class='long-text content', _id='newlink')">
|
||||
%if not thing.subreddits:
|
||||
<input type="hidden" name="sr" value="${c.site.name}" />
|
||||
%endif
|
||||
<input type="hidden" name="then" value="${thing.then}" />
|
||||
<table>
|
||||
<tr>
|
||||
<th>
|
||||
|
||||
@@ -54,11 +54,12 @@ thing id-${what._fullname}
|
||||
<%def name="RenderPrintable()">
|
||||
<% cls = thing.lookups[0].__class__.__name__.lower() %>
|
||||
<%
|
||||
if hasattr(thing, 'render_class'):
|
||||
cls = thing.render_class
|
||||
if hasattr(thing, 'render_css_class'):
|
||||
cls = thing.render_css_class
|
||||
elif hasattr(thing, 'render_class'):
|
||||
cls = thing.render_class.__name__.lower()
|
||||
else:
|
||||
cls = thing.lookups[0].__class__
|
||||
cls = cls.__name__.lower()
|
||||
cls = thing.lookups[0].__class__.__name__.lower()
|
||||
|
||||
if thing.show_spam:
|
||||
rowclass = thing.rowstyle + " spam"
|
||||
@@ -145,6 +146,11 @@ thing id-${what._fullname}
|
||||
%if thing.deleted and not c.user_is_admin:
|
||||
[deleted]
|
||||
%else:
|
||||
<%
|
||||
target = None
|
||||
if hasattr(thing, "target"):
|
||||
target = thing.target
|
||||
%>
|
||||
%if thing.author._deleted:
|
||||
<span>[deleted]</span>
|
||||
%else:
|
||||
@@ -155,11 +161,12 @@ thing id-${what._fullname}
|
||||
author_cls += " friend"
|
||||
elif gray:
|
||||
author_cls += " gray"
|
||||
name = websafe(author.name)
|
||||
href = unsafe('href="%s"' % add_sr("/user/%s/" % name, sr_path = False))
|
||||
if c.user_is_admin: name += " (%d)" % (author.link_karma)
|
||||
disp_name = websafe(author.name)
|
||||
if c.user_is_admin:
|
||||
disp_name += " (%d)" % (author.link_karma)
|
||||
%>
|
||||
<a class="${author_cls}" ${href}>${name}</a>
|
||||
${plain_link(disp_name, '/user/%s' % websafe(author.name),
|
||||
_class = author_cls, _sr_path = False, target=target)}
|
||||
%endif
|
||||
%endif
|
||||
%if c.user_is_admin and hasattr(thing, 'ip') and thing.ip:
|
||||
@@ -184,25 +191,26 @@ thing id-${what._fullname}
|
||||
</div>
|
||||
</%def>
|
||||
|
||||
<%def name="score(this, likes=None, inline=True)">
|
||||
<%def name="score(this, likes=None, tag='span', score_fmt = None)">
|
||||
<%
|
||||
tag = "span" if inline else "div"
|
||||
_class = "" if likes is None else "likes" if likes else "dislikes"
|
||||
|
||||
# figure out alterna-points
|
||||
score = this.score
|
||||
base_score = score - 1 if likes else score if likes is None else score + 1
|
||||
base_score = [base_score + x for x in range(-1, 2)];
|
||||
|
||||
|
||||
if score_fmt is None:
|
||||
score_fmt = thing.score_fmt
|
||||
%>
|
||||
<${tag} class="score ${_class}">
|
||||
${thing.score_fmt(this.score)}
|
||||
${score_fmt(this.score)}
|
||||
</${tag}>
|
||||
<script type="text/javascript">
|
||||
if(reddit)
|
||||
reddit.vl['${this._fullname}'] = ['${thing.score_fmt(base_score[0])}',
|
||||
'${thing.score_fmt(base_score[1])}',
|
||||
'${thing.score_fmt(base_score[2])}' ];
|
||||
reddit.vl['${this._fullname}'] = ['${score_fmt(base_score[0])}',
|
||||
'${score_fmt(base_score[1])}',
|
||||
'${score_fmt(base_score[2])}' ];
|
||||
</script>
|
||||
</%def>
|
||||
|
||||
|
||||
@@ -73,6 +73,16 @@
|
||||
<link rel="alternate" type="application/rss+xml" title="RSS"
|
||||
href="${add_sr(join_urls(request.path,'.rss'))}" />
|
||||
%endif
|
||||
|
||||
<!--[if lt IE 7]>
|
||||
<link rel="stylesheet" href="${static('reddit-ie6-hax.css')}""
|
||||
type="text/css" />
|
||||
<![endif]-->
|
||||
|
||||
<!--[if lt IE 8]>
|
||||
<link rel="stylesheet" href="${static('reddit-ie7-hax.css')}""
|
||||
type="text/css" />
|
||||
<![endif]-->
|
||||
</%def>
|
||||
|
||||
<%def name="javascript()">
|
||||
@@ -81,10 +91,6 @@
|
||||
<script src="${static('jquery.json.js')}" type="text/javascript"></script>
|
||||
<script src="${static('jquery.reddit.js')}" type="text/javascript"></script>
|
||||
<script src="${static('reddit.js')}" type="text/javascript"></script>
|
||||
<!--[if lt IE 7]>
|
||||
<link rel="stylesheet" href="${static('reddit-ie6-hax.css')}""
|
||||
type="text/css" />
|
||||
<![endif]-->
|
||||
</%def>
|
||||
|
||||
<%def name="javascript_run()">
|
||||
@@ -110,7 +116,10 @@
|
||||
</div>
|
||||
%endif
|
||||
|
||||
<%include file="redditfooter.html"/>
|
||||
%if thing.footer:
|
||||
<%include file="redditfooter.html"/>
|
||||
%endif
|
||||
|
||||
${framebuster()}
|
||||
|
||||
</body>
|
||||
|
||||
@@ -72,12 +72,14 @@
|
||||
mail_img ="mail"
|
||||
if c.have_messages:
|
||||
mail_img += ".png"
|
||||
mail_img_class = 'havemail'
|
||||
else:
|
||||
mail_img += "gray.png"
|
||||
mail_img_class = 'nohavemail'
|
||||
mail_img = static(mail_img)
|
||||
%>
|
||||
${img_link(_("messages"), mail_img, path="/message/inbox/",
|
||||
_id = "mail" )}
|
||||
_id = "mail", _class=mail_img_class)}
|
||||
${separator("|")}
|
||||
%endif
|
||||
|
||||
|
||||
32
r2/r2/templates/redditmin.html
Normal file
@@ -0,0 +1,32 @@
|
||||
## The contents of this file are subject to the Common Public Attribution
|
||||
## License Version 1.0. (the "License"); you may not use this file except in
|
||||
## compliance with the License. You may obtain a copy of the License at
|
||||
## http://code.reddit.com/LICENSE. The License is based on the Mozilla Public
|
||||
## License Version 1.1, but Sections 14 and 15 have been added to cover use of
|
||||
## software over a computer network and provide for limited attribution for the
|
||||
## Original Developer. In addition, Exhibit A has been modified to be consistent
|
||||
## with Exhibit B.
|
||||
##
|
||||
## Software distributed under the License is distributed on an "AS IS" basis,
|
||||
## WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for
|
||||
## the specific language governing rights and limitations under the License.
|
||||
##
|
||||
## The Original Code is Reddit.
|
||||
##
|
||||
## The Original Developer is the Initial Developer. The Initial Developer of
|
||||
## the Original Code is CondeNet, Inc.
|
||||
##
|
||||
## All portions of the code written by CondeNet are Copyright (c) 2006-2009
|
||||
## CondeNet, Inc. All Rights Reserved.
|
||||
############
|
||||
<%inherit file="reddit.html"/>
|
||||
|
||||
<%def name="bodyHTML()">
|
||||
<body onclick="close_menus()" class="min-body">
|
||||
%if thing.content:
|
||||
<div class="content">
|
||||
${thing.content().render()}
|
||||
</div>
|
||||
%endif
|
||||
</body>
|
||||
</%def>
|
||||
44
r2/r2/templates/starkcomment.html
Normal file
@@ -0,0 +1,44 @@
|
||||
## The contents of this file are subject to the Common Public Attribution
|
||||
## License Version 1.0. (the "License"); you may not use this file except in
|
||||
## compliance with the License. You may obtain a copy of the License at
|
||||
## http://code.reddit.com/LICENSE. The License is based on the Mozilla Public
|
||||
## License Version 1.1, but Sections 14 and 15 have been added to cover use of
|
||||
## software over a computer network and provide for limited attribution for the
|
||||
## Original Developer. In addition, Exhibit A has been modified to be consistent
|
||||
## with Exhibit B.
|
||||
##
|
||||
## Software distributed under the License is distributed on an "AS IS" basis,
|
||||
## WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for
|
||||
## the specific language governing rights and limitations under the License.
|
||||
##
|
||||
## The Original Code is Reddit.
|
||||
##
|
||||
## The Original Developer is the Initial Developer. The Initial Developer of
|
||||
## the Original Code is CondeNet, Inc.
|
||||
##
|
||||
## All portions of the code written by CondeNet are Copyright (c) 2006-2009
|
||||
## CondeNet, Inc. All Rights Reserved.
|
||||
################################################################################
|
||||
<%inherit file="comment.html"/>
|
||||
|
||||
<%def name="entry()">
|
||||
<div class="commentbox">
|
||||
<span class="commentbody">
|
||||
${self.commentBody()}
|
||||
</span>
|
||||
<p class="tagline">
|
||||
${self.tagline()}
|
||||
<a target="_top" href="${thing.permalink}">
|
||||
 
|
||||
${_("context")}
|
||||
</a>
|
||||
</p>
|
||||
</div>
|
||||
</%def>
|
||||
|
||||
<%def name="tagline(**kw)">
|
||||
${parent.tagline(collapse=False,showexpandcollapse=False,**kw)}
|
||||
</%def>
|
||||
|
||||
<%def name="arrow(*a, **kw)">
|
||||
</%def>
|
||||
@@ -52,7 +52,11 @@ id="${arg}_${thing and thing._fullname or ''}"
|
||||
|
||||
<%def name="submit_form(onsubmit='', action='', _class='', method='post', _id='', **params)">
|
||||
<form class="pretty-form ${_class or ''}" onsubmit="${onsubmit or ''}"
|
||||
action="${action or ''}" ${_id and "id='" + _id + "'" or ""} method="${method}">
|
||||
action="${action or ''}" ${_id and "id='" + _id + "'" or ""} method="${method}"
|
||||
%if c.cname:
|
||||
target="_top"
|
||||
%endif
|
||||
>
|
||||
%if c.user_is_loggedin:
|
||||
<input type="hidden" name="uh" value="${c.user.modhash()}" />
|
||||
%endif
|
||||
@@ -367,10 +371,23 @@ ${unsafe(txt)}
|
||||
};
|
||||
</%def>
|
||||
|
||||
<%def name="logout()">
|
||||
<form method="post" action="/logout" class="logout hover">
|
||||
<%def name="logout(top=False,dest=None,a_class='')">
|
||||
<form method="post" action="/logout" class="logout hover"
|
||||
%if top:
|
||||
target="_top"
|
||||
%endif
|
||||
>
|
||||
<input type="hidden" name="uh" value="${c.modhash}"/>
|
||||
<a href="javascript:void(0)" onclick="$(this).parent().submit()">
|
||||
<input type="hidden" name="top" value="${'on' if top else 'off'}"/>
|
||||
%if dest:
|
||||
<input type="hidden" name="dest" value="${dest}"/>
|
||||
%endif
|
||||
|
||||
<a href="javascript:void(0)" onclick="$(this).parent().submit()"
|
||||
%if a_class:
|
||||
class="${a_class}"
|
||||
%endif
|
||||
>
|
||||
${_("logout")}
|
||||
</a>
|
||||
</form>
|
||||
|
||||