Better error handling when error handler fails. Buttons allow url to be specified as a get parameter. Also support a newwindow option for target=_new. Currently undocumented button types 4 and 5 included as well. Widget supports in place voting. Socialite toolbar included help page and link to xpi file.

This commit is contained in:
KeyserSosa
2008-10-22 14:08:50 -07:00
parent ad38d86315
commit 61b3894755
32 changed files with 582 additions and 110 deletions

View File

@@ -64,6 +64,7 @@ def make_map(global_conf={}, app_conf={}):
mc('/buttonlite', controller='buttons', action='button_lite')
mc('/widget', controller='buttons', action='widget_demo_page')
mc('/socialite', controller='buttons', action='socialite_demo_page')
mc('/bookmarklets', controller='buttons', action='bookmarklets')
mc('/stats', controller='front', action='stats')

View File

@@ -21,9 +21,10 @@
################################################################################
from reddit_base import RedditController
from r2.lib.pages import Button, ButtonNoBody, ButtonEmbed, ButtonLite, \
ButtonDemoPanel, WidgetDemoPanel, Bookmarklets, BoringPage
ButtonDemoPanel, WidgetDemoPanel, Bookmarklets, BoringPage, Socialite
from r2.models import *
from r2.lib.strings import Score
from r2.lib.utils import tup
from pylons import c, request
from validator import *
from pylons.i18n import _
@@ -36,29 +37,43 @@ class ButtonsController(RedditController):
except ValueError:
return 1
@validate(url = nop('url'),
def get_link(self, url):
try:
sr = None if isinstance(c.site, FakeSubreddit) else c.site
links = tup(Link._by_url(url, sr))
#find the one with the highest score
return max(links, key = lambda x: x._score)
except:
#we don't want to return 500s in other people's pages.
import traceback
g.log.debug("FULLPATH: get_link error in buttons code")
g.log.debug(traceback.format_exc())
def wrap_link(self, link):
if link and hasattr(link, "_fullname"):
rs = c.render_style
c.render_style = 'html'
from r2.controllers.listingcontroller import ListingController
link_builder = IDBuilder(link._fullname, wrap = ListingController.builder_wrapper)
# link_listing will be the one-element listing at the top
link_listing = LinkListing(link_builder, nextprev=False).listing()
# link is a wrapped Link object
c.render_style = rs
return link_listing.things[0]
@validate(url = VSanitizedUrl('url'),
title = nop('title'),
css = nop('css'),
vote = VBoolean('vote', default=True),
newwindow = VBoolean('newwindow'),
width = VInt('width', 0, 300))
def GET_button_content(self, url, title, css, vote, newwindow, width):
try:
links = Link._by_url(url,None)
#find the one with the highest score
l = max(links, key = lambda x: x._score)
likes = Vote.likes(c.user, l) if c.user_is_loggedin else {}
likes = likes.get((c.user, l))
if likes:
likes = (True if likes._name == '1'
else False if likes._name == '-1'
else None)
except:
#the only time we're gonna have an empty except. we don't
#want to return 500s in other people's pages.
l = likes = None
width = VInt('width', 0, 800),
link = VByName('id'))
def GET_button_content(self, url, title, css, vote, newwindow, width, link):
l = self.wrap_link(link or self.get_link(url))
if l: url = l.url
#disable css hack
if (css != 'http://blog.wired.com/css/redditsocial.css' and
css != 'http://www.wired.com/css/redditsocial.css'):
@@ -78,57 +93,56 @@ class ButtonsController(RedditController):
target = "_new"
else:
target = "_parent"
c.response.content = page_handler(button=self.buttontype(), css=css,
c.response.content = page_handler(button=bt, css=css,
score_fmt = score_fmt, link = l,
likes = likes, url=url, title=title,
url=url, title=title,
vote = vote, target = target,
bgcolor=c.bgcolor, width=width).render()
return c.response
@validate(buttontype = VInt('t', 1, 3),
@validate(buttontype = VInt('t', 1, 5),
url = VSanitizedUrl("url"),
_height = VInt('height', 0, 300),
_width = VInt('width', 0, 300))
def GET_button_embed(self, buttontype, _height, _width):
def GET_button_embed(self, buttontype, _height, _width, url):
c.render_style = 'js'
c.response_content_type = 'text/javascript; charset=UTF-8'
buttontype = buttontype or 1
width, height = ((120, 22), (51, 69), (69, 52))[buttontype - 1]
width, height = ((120, 22), (51, 69), (69, 52), (51, 52), (600, 52))[min(buttontype - 1, 4)]
if _width: width = _width
if _height: height = _height
bjs = ButtonEmbed(button=buttontype,
width=width,
height=height,
url = url,
referer = request.referer).render()
# we doing want the JS to be cached!
c.used_cache = True
return self.sendjs(bjs, callback='', escape=False)
@validate(buttonimage = VInt('i', 0, 14),
url = nop('url'),
url = VSanitizedUrl('url'),
newwindow = VBoolean('newwindow', default = False),
styled = VBoolean('styled', default=True))
def GET_button_lite(self, buttonimage, url, styled):
def GET_button_lite(self, buttonimage, url, styled, newwindow):
c.render_style = 'js'
c.response_content_type = 'text/javascript; charset=UTF-8'
if not url:
url = request.referer
try:
links = Link._by_url(url,None)
#find the one with the highest score
l = max(links, key = lambda x: x._score)
except:
#we don't want to return 500s in other people's pages.
l = None
if buttonimage == None:
image = 1
if newwindow:
target = "_new"
else:
image = buttonimage
target = "_parent"
bjs = ButtonLite(image = image, link = l, url = url, styled = styled).render()
l = self.wrap_link(self.get_link(url))
image = 1 if buttonimage is None else buttonimage
bjs = ButtonLite(image = image, link = l, url = l.url if l else url,
target = target, styled = styled).render()
# we don't want the JS to be cached!
c.used_cache = True
return self.sendjs(bjs, callback='', escape=False)
@@ -146,6 +160,11 @@ class ButtonsController(RedditController):
show_sidebar = False,
content=WidgetDemoPanel()).render()
def GET_socialite_demo_page(self):
return BoringPage(_("socialite toolbar"),
show_sidebar = False,
content=Socialite()).render()
def GET_bookmarklets(self):
return BoringPage(_("bookmarklets"),

View File

@@ -99,13 +99,7 @@ class ErrorController(RedditController):
try:
return RedditController.__call__(self, environ, start_response)
except:
if g.debug:
# if we're in debug mode, let this hit Pylons so we
# get a stack trace
raise
else:
c.response.content = "something really awful just happened"
return c.response
return handle_awful_failure("something really awful just happened.")
def send403(self):
@@ -154,5 +148,24 @@ class ErrorController(RedditController):
else:
return "page not found"
except:
return "something really bad just happened"
return handle_awful_failure("something really bad just happened.")
def handle_awful_failure(fail_text):
"""
Makes sure that no errors generated in the error handler percolate
up to the user unless debug is enabled.
"""
if g.debug:
import sys
s = sys.exc_info()
# reraise the original error with the original stack trace
raise s[1], None, s[2]
try:
# log the traceback, and flag the "path" as the error location
import traceback
g.log.debug("FULLPATH: %s" % fail_text)
g.log.debug(traceback.format_exc())
return redditbroke % fail_text
except:
# we are doomed. Admit defeat
return "This is an error that should never occur. You win."

View File

@@ -335,9 +335,10 @@ class ByIDController(ListingController):
def query(self):
return self.names
link_prefix = Link._type_prefix + str(Link._type_id)
@validate(VRegex('names', r'^('+link_prefix+'_[0-9a-z]+ ?)+$'))
@validate(names = VLinkFullnames("names"))
def GET_listing(self, names, **env):
if not names:
return self.abort404()
self.names = names.split(' ')
return ListingController.GET_listing(self, **env)

View File

@@ -192,19 +192,19 @@ def chksrname(x):
except UnicodeEncodeError:
return None
class VRegex(Validator):
def __init__(self, item, rg, *a, **kw):
self.item = item
self.valid = re.compile(rg).match
class VLinkFullnames(Validator):
valid_re = re.compile(r'^(' + Link._type_prefix + str(Link._type_id) +
'_[0-9a-z]+ ?)+$')
def __init__(self, item, *a, **kw):
self.item = item
Validator.__init__(self, item, *a, **kw)
def run(self, val):
if val is None or not self.valid(val):
abort('400','bad request')
else:
if val and self.valid_re.match(val):
return val
class VLength(Validator):
def __init__(self, item, length = 10000,
empty_error = errors.BAD_COMMENT,
@@ -455,6 +455,10 @@ class VLogin(VRequired):
return user
class VSanitizedUrl(Validator):
def run(self, url):
return utils.sanitize_url(url)
class VUrl(VRequired):
def __init__(self, item, *a, **kw):
VRequired.__init__(self, item, errors.NO_URL, *a, **kw)
@@ -735,6 +739,9 @@ class VCnameDomain(Validator):
except UnicodeEncodeError:
c.errors.add(errors.BAD_CNAME)
# NOTE: make sure *never* to have res check these are present
# otherwise, the response could contain reference to these errors...!
class ValidIP(Validator):

View File

@@ -91,6 +91,7 @@ menu = MenuHandler(hot = _('hot'),
#reddit footer strings
feedback = _("feedback"),
bookmarklets = _("bookmarklets"),
socialite = _("socialite"),
buttons = _("buttons"),
widget = _("widget"),
code = _("code"),

View File

@@ -192,8 +192,9 @@ class Reddit(Wrapped):
"""navigation buttons in the footer."""
buttons = [NamedButton("feedback", False),
NamedButton("bookmarklets", False),
NamedButton("buttons", False),
NamedButton("widget", False),
NamedButton("socialite", False),
NamedButton("buttons", True),
NamedButton("widget", True),
NamedButton("code", False, nocname=True),
NamedButton("mobile", False, nocname=True),
NamedButton("store", False, nocname=True),
@@ -852,22 +853,23 @@ class UserStats(Wrapped):
class ButtonEmbed(Wrapped):
"""Generates the JS wrapper around the buttons for embedding."""
def __init__(self, button = None, width = 100, height=100, referer = ""):
def __init__(self, button = None, width = 100, height=100, referer = "", url = ""):
Wrapped.__init__(self, button = button, width = width, height = height,
referer=referer)
referer=referer, url = url)
class ButtonLite(Wrapped):
"""Generates the JS wrapper around the buttons for embedding."""
def __init__(self, image = None, link = None, url = "", styled = True):
Wrapped.__init__(self, image = image, link = link, url = url, styled = styled)
def __init__(self, image = None, link = None, url = "", styled = True, target = '_top'):
Wrapped.__init__(self, image = image, link = link, url = url, styled = styled, target = target)
class Button(Wrapped):
"""the voting buttons, embedded with the ButtonEmbed wrapper, shown on /buttons"""
extension_handling = False
def __init__(self, link = None, likes = None, button = None, css=None,
def __init__(self, link = None, button = None, css=None,
url = None, title = '', score_fmt = None, vote = True, target = "_parent",
bgcolor = None, width = 100):
Wrapped.__init__(self, link = link, likes = likes, score_fmt = score_fmt,
Wrapped.__init__(self, link = link, score_fmt = score_fmt,
likes = link.likes if link else None,
button = button, css = css, url = url, title = title,
vote = vote, target = target, bgcolor=bgcolor, width=width)
@@ -893,6 +895,10 @@ class WidgetDemoPanel(Wrapped):
"""Demo page for the .embed widget."""
pass
class Socialite(Wrapped):
"""Demo page for the socialite Firefox extension"""
pass
class Bookmarklets(Wrapped):
"""The bookmarklets page."""
def __init__(self, buttons=["reddit", "like", "dislike",

View File

@@ -212,7 +212,11 @@ class Link(Thing, Printable):
# htmllite depends on other get params
s = ''.join(s)
if c.render_style == "htmllite":
s += str(request.get.has_key('style'))
s += ''.join(map(str, [request.get.has_key('style'),
request.get.has_key('expanded'),
request.get.has_key('twocolumn'),
c.bgcolor,
c.bordercolor]))
return s
def make_permalink(self, sr, force_domain = False):

View File

@@ -1174,6 +1174,52 @@ a.star { text-decoration: none; color: #ff8b60 }
.button .blog3 .arrow { width: 100% }
.button .blog3 .right { float: right; margin-top: 5px; }
.blog5 .right { float: right; }
.blog5 .left { float: left; display:block; margin-top: 10px; }
.blog5 .clearleft { clear: left; }
.button .blog.blog5 { border: none; text-align: left; font-size: small; }
.blog5 .container { margin-left: 35px; margin-top: 2px; height: 50px;}
.blog5 ul { display: inline; }
.blog5 ul a { color: #515481; font-weight: bold; text-decoration: underline; }
.blog5 li { display: inline; padding: 1px 10px 1px 10px; }
.blog5 li.selected {
background-color: #F8F8F1;
color: #000;
border-color: #CCC;
border-style: solid solid none solid;
border-width: 1px;
}
.blog5 .votes {
height: 25px;
background-color: #F8F8F1;
border: 1px solid #CCC;
padding-top: 5px;
}
.blog5 .arrow {
margin-right: 15px;
margin-left: 5px;
color: black;
cursor: pointer;
display: inline;
background-position: left center;
background-repeat: no-repeat;
padding-left: 20px;
}
.blog5 .votes.disabled .arrow { color: #888; }
.blog5 .arrow:hover { text-decoration: none; }
.blog5 .arrow b { font-size: larger; }
.blog5 .arrow.upmod b { color: #FF8B60; }
.blog5 .arrow.downmod b { color: #9494FF; }
.blog5 .right { margin-right: 5px; font-size: medium; font-style: italic; }
.blog5 .controversy3 { color: #BB2222;}
.blog5 .controversy2 { color: #AB4242;}
.blog5 .controversy1 { color: #976B6B;}
.blog5 .controversy0 { color: #A8A8A8;}
.optional {color: green}
.instructions { font-size: larger; }
.instructions h1, .instructions h2, .instructions h3 { margin-top: 20px; margin-bottom: 20px; }
@@ -1196,13 +1242,14 @@ a.star { text-decoration: none; color: #ff8b60 }
padding: 10px;
max-width: 50em;}
#preview { float: right; width: 30em; margin-right: 10px; }
#preview { float: right; width: 30em; margin: 10px; }
#preview span { color: lightgray; }
#preview #previewbox {
border-width: .2em;
border-style: dashed;
border-color: lightgray;
padding: 1em;
font-size: larger;
}
/* the toolbar */
@@ -1418,3 +1465,81 @@ ul#image-preview-list .description pre {
float: left;
}
/* Socialite */
.socialite.instructions ul {
margin: 10px;
max-width: 60em;
}
.socialite.instructions ul > li {
list-style-type: disc;
list-style-position: inside;
}
.socialite.instructions hr {
color: #C6C6C6;
border: none;
border-top: 1px solid #C6C6C6;
margin: 20px 0px 20px 0px;
max-width: 60em;
}
.socialite.instructions p.screenshot {
text-align: center;
}
.socialite.instructions .logotext {
line-height: 32px;
}
.socialite.instructions .logotext .logo {
float: left;
margin-right: 10px;
}
.socialite.instructions .logoclear {
clear: left;
}
.socialite.instructions .features {
padding-left: 15px;
max-width: 60em;
}
/* From http://www.oscaralexander.com/tutorials/how-to-make-sexy-buttons-with-css.html */
.socialite .buttonclear {
overflow: hidden;
float: right;
margin-right: 20px;
}
.socialite a.installbutton {
background: transparent url(/static/socialite/installbutton-end.png) no-repeat scroll top right;
color: #FFF;
display: block;
float: left;
font: bold 18px "Trebuchet MS",Helvetica,"Helvetica Neue",Arial,sans-serif;
height: 50px;
margin-right: 6px;
padding-right: 48px; /* sliding doors padding */
text-decoration: none;
}
.socialite a.installbutton span {
background: transparent url(/static/socialite/installbutton.png) no-repeat;
display: block;
line-height: 30px;
padding: 10px 0 10px 17px;
}
.socialite a.installbutton:hover {
background-position: bottom right;
}
.socialite a.installbutton:hover span {
background-position: bottom left;
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 49 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 30 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 56 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 291 B

After

Width:  |  Height:  |  Size: 290 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 409 B

After

Width:  |  Height:  |  Size: 408 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 414 B

After

Width:  |  Height:  |  Size: 413 B

View File

@@ -28,22 +28,29 @@
%>
<div class="rembeddit"
${optionalstyle("font-family:verdana,arial,helvetica,sans-serif;padding:5px;" + style_line(bgcolor="FFFFFF", bordercolor="336699"))}>
${optionalstyle("font-family:verdana,arial,helvetica,sans-serif;" + style_line(bgcolor="FFFFFF", bordercolor="336699"))}>
<h3 class="reddit-title" ${optionalstyle("margin:0;")}>
<div class="reddit-header"
${optionalstyle("padding: 5px; padding-bottom:1px;" + ("background-color:#CEE3F8" if not c.bgcolor else ""))}>
<h4 class="reddit-title"
${optionalstyle("margin:0;" + ("padding-bottom:3px" if not c.cname else ""))}
>
<a href="http://${get_domain()}/" ${optionalstyle("margin:5px;")}>
<img src="http://${get_domain(subreddit=False)}/static/spreddit1.gif" alt=""
${optionalstyle("border:none")} />
</a>
<%
style = capture(optionalstyle, "text-decoration:none;color:#336699")
link = '<a %s href="http://%s/">%s</a></h3>' % (style, get_domain(), c.site.name)
name = c.site.name
if not isinstance(c.site, FakeSubreddit):
name += ".%s" % g.domain
link = '<a %s href="http://%s/">%s</a></h3>' % (style, get_domain(), name)
label = _("links from %(site)s").replace(" ", "&#32;");
%>
%>
${unsafe(label % dict(site = link))}
</h3>
%if not isinstance(c.site, FakeSubreddit) or c.site != Default:
<p ${optionalstyle("margin: 0px 30px 10px 30px; color: gray;")}
</h4>
%if c.cname:
<p ${optionalstyle("margin: 0px 30px 5px 30px; color: gray;")}
class="powered-by-reddit">
<small>
powered by&#32;
@@ -54,6 +61,8 @@
</small>
</p>
%endif
${next.body()}
</div>
<div class="rembeddit-content" ${optionalstyle("padding:5px;")}>
${next.body()}
</div>
</div>

View File

@@ -32,7 +32,10 @@
<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>
<h2>${_("in Firefox")}</h2>
<p>
${_("click and drag")}&nbsp;
Try out our new firefox add-on, &#32;<a href="/socialite">Socialite</a>.
</p>
<p>
or ${_("click and drag")}&nbsp;
%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" />

View File

@@ -25,7 +25,7 @@
%>
<%inherit file="reddit.html"/>
<%namespace module="r2.lib.template_helpers" import="generateurl"/>
<%namespace file="buttontypes.html" import="button1, button2, button3, submiturl, submitlink" />
<%namespace file="buttontypes.html" import="*" />
@@ -41,7 +41,7 @@
</%def>
<%def name="bodyHTML()">
<body>
<body style="background-color: ${'#%s' % (c.bgcolor or 'FFFFFF')}">
<div class="button">
%if not c.user_is_loggedin:
<div id="cover" style="display: none">
@@ -58,6 +58,10 @@
${button2(thing)}
%elif thing.button == 3:
${button3(thing)}
%elif thing.button == 4:
${button4(thing)}
%elif thing.button == 5:
${button5(thing)}
%endif
</div>
</body>

View File

@@ -50,12 +50,14 @@
%endfor
</ul>
<h2>${_("customizing the look of your buttons")}</h2>
<p>${_('the buttons with points have two additional options.')}</p>
<p>${_('the buttons with points have three additional options.')}</p>
<ul class="buttons" >
<li><strong>styled=off</strong><br />
${_('no styles will be added, so you can style it yourself')}</li>
<li><strong>url=[URL]</strong><br />
${_('specify a url to use instead of the current url')}</li>
<li><strong>newwindow=1</strong><br />
${_('opens links in a new window')}</li>
</ul>
<p>${_('Example:')}</p>
<code>
@@ -88,6 +90,10 @@
<p><strong>${_("specify a title")}</strong></p>
<code>${drawoption('title','[TITLE]')}</code>
</li>
<li>
<p><strong>${_("open links in a new window")}</strong></p>
<code>${drawoption('newwindow','1')}</code>
</li>
<li>
<p><strong>${_("specify the color")}</strong></p>
<code>${drawoption('bgcolor','[COLOR]')}</code>
@@ -119,7 +125,7 @@
<%def name="drawbadge(image)">
<a href="http://${domain}/submit"
onclick="window.location = 'http://${domain}/submit?url=' + encodeURIComponent(window.location); return false">
<img src="http://${domain}/static/spreddit${image}.gif" alt="submit to reddit" border="0" />
<img src="http://${get_domain(subreddit=False)}/static/spreddit${image}.gif" alt="submit to reddit" border="0" />
</a>
</%def>
@@ -137,7 +143,7 @@ onclick="window.location = 'http://${domain}/submit?url=' + encodeURIComponent(w
</%def>
<%def name="point_option_example()">
<script type="text/javascript" src="http://${domain}/buttonlite.js?i=1&styled=off&url=foo.com"></script>
<script type="text/javascript" src="http://${domain}/buttonlite.js?i=1&styled=off&url=foo.com&newwindow=1"></script>
</%def>
<%def name="point_button_demo(image)">

View File

@@ -28,14 +28,16 @@
arg = "cnameframe=1&" if c.cname else ""
%>
(function() {
var write_string='<iframe src="http://${domain}/button_content?${arg}t=${thing.button}&url=';
var write_string="<iframe src=\"http://${domain}/button_content?${arg}t=${thing.button}&width=${thing.width}&url=${thing.url or ""}";
%if not thing.url:
if (window.reddit_url) { write_string += encodeURIComponent(reddit_url); }
else { write_string += encodeURIComponent('${thing.referer}');}
if (window.reddit_title) { write_string += '&title=' + encodeURIComponent(reddit_title); }
if (window.reddit_css) { write_string += '&css=' + encodeURIComponent(reddit_css); }
if (window.reddit_bgcolor) { write_string += '&bgcolor=' + encodeURIComponent(reddit_bgcolor); }
if (window.reddit_bordercolor) { write_string += '&bordercolor=' + encodeURIComponent(reddit_bordercolor); }
write_string += '&width=${thing.width}';
write_string += '" height="${thing.height}" width="${thing.width}" scrolling="no" frameborder="0"></iframe>';
%endif
if (window.reddit_title) { write_string += '&title=' + encodeURIComponent(window.reddit_title); }
if (window.reddit_css) { write_string += '&css=' + encodeURIComponent(window.reddit_css); }
if (window.reddit_bgcolor) { write_string += '&bgcolor=' + encodeURIComponent(window.reddit_bgcolor); }
if (window.reddit_bordercolor) { write_string += '&bordercolor=' + encodeURIComponent(window.reddit_bordercolor); }
if (window.reddit_newwindow) { write_string += '&newwindow=' + encodeURIComponent(window.reddit_newwindow);}
write_string += "\" height=\"${thing.height}\" width=\"${thing.width}\" scrolling='no' frameborder='0'></iframe>";
document.write(write_string);
})()

View File

@@ -28,19 +28,17 @@
<%
domain = get_domain()
if thing.link:
thing.link.score = thing.link._ups - thing.link._downs
%>
(function() {
var styled_submit = '<a style="color: #369; text-decoration: none;" href="${submiturl(thing.url)}">';
var unstyled_submit = '<a href="${submiturl(thing.url)}">';
var styled_submit = '<a style="color: #369; text-decoration: none;" href="${submiturl(thing.url)}" target="${thing.target}">';
var unstyled_submit = '<a href="${submiturl(thing.url)}" target="${thing.target}">';
var write_string='<span class="reddit_button" style="';
%if thing.styled:
write_string += 'color: grey;';
%endif
write_string += '">';
%if thing.image > 0:
write_string += '<img style="height: 2.3ex; vertical-align:top; margin-right: 1ex" src="http://${domain}/static/spreddit${thing.image}.gif">';
write_string += unstyled_submit + '<img style="height: 2.3ex; vertical-align:top; margin-right: 1ex" src="http://${get_domain(subreddit=False)}/static/spreddit${thing.image}.gif">' + "</a>";
%endif
%if thing.link:
write_string += '${Score.safepoints(thing.link.score)}';

View File

@@ -28,4 +28,8 @@
${button2(thing)}
%elif thing.button == 3:
${button3(thing)}
%elif thing.button == 4:
${button4(thing)}
%elif thing.button == 5:
${button5(thing)}
%endif

View File

@@ -27,7 +27,7 @@
<%namespace file="printable.html" import="arrow, score" />
<%namespace file="utils.html" import="img_link" />
<%def name="submiturl(url, title='')">${("http://%s/submit" % get_domain(True)) + query_string(dict(url=url, title=title))}</%def>
<%def name="submiturl(url, title='')">${("http://%s/submit" % get_domain(cname = c.cname)) + query_string(dict(url=url, title=title))}</%def>
<%def name="submitlink(url, title='', text='submit')">
<a href='${submiturl(url, title)}' target='${thing.target}'>${text}</a>
@@ -49,7 +49,6 @@ ${class_def(1, width=choose_width(thing.link, thing.width))}
</a>
</div>
%if thing.link:
<% thing.link.score = thing.link._ups - thing.link._downs %>
%if thing.vote:
${arrow(thing.link, 1, thing.likes)}
${arrow(thing.link, 0, thing.likes == False)}
@@ -67,7 +66,6 @@ ${class_def(1, width=choose_width(thing.link, thing.width))}
<%def name="button2(thing)">
${class_def(2)}
%if thing.link:
<% thing.link.score = thing.link._ups - thing.link._downs %>
%if thing.vote:
${arrow(thing.link, 1, thing.likes)}
${score(thing.link, thing.likes, inline=False, label = False)}
@@ -96,7 +94,6 @@ ${class_def(1, width=choose_width(thing.link, thing.width))}
${class_def(3)}
<div class="left">
%if thing.link:
<% thing.link.score = thing.link._ups - thing.link._downs %>
%if thing.vote:
${arrow(thing.link, 1, thing.likes)}
${score(thing.link, thing.likes, inline=False, label = False)}
@@ -113,8 +110,139 @@ ${class_def(3)}
%endif
</div>
<div class="right">
${img_link('submit', '/static/blog_snoo.gif', '/submit' + query_string(dict(url=thing.url, title=thing.title)))}
${img_link('submit', '/static/blog_snoo.gif', capture(submiturl, thing.url, thing.title))}
</div>
<div class="clear"></div>
</div>
</%def>
<%def name="button4(thing)">
${class_def(2)}
%if thing.link:
%if thing.vote:
${arrow(thing.link, 1, thing.likes)}
${score(thing.link, thing.likes, inline=False, label = False)}
${arrow(thing.link, 0, thing.likes == False)}
%else:
&nbsp;<br />
${thing.link.score}
&nbsp;<br />
%endif
%else:
<img src="http://www.reddit.com/static/blog_head.png" alt=""/>
${submitlink(thing.url, thing.title, 'submit to')}
%endif
</div>
</%def>
<%def name="button5(thing)">
${class_def(5, width=choose_width(thing.link, thing.width))}
${img_link('submit', '/static/blog_snoo.gif', capture(submiturl, thing.url, thing.title), _class="left")}
<%
submitlink = capture(submiturl, thing.url, thing.title)
if thing.link:
fullname = thing.link._fullname
ups = thing.link.upvotes
downs = thing.link.downvotes
if hasattr(c.site, "domain"):
c.cname = True
link = "http://%s%s" % (get_domain(cname = True, subreddit = False),
thing.link.make_permalink_slow())
else:
fullname = ""
ups = 0
downs = 0
link = submitlink
if c.user_is_loggedin:
dir = 1 if thing.likes else 0 if thing.likes is None else -1
ups = ups - (1 if dir > 0 else 0)
downs = downs - (1 if dir < 0 else 0)
else:
dir = 0
other_votes = float(ups + downs)
ups = [ups, ups, ups + 1]
downs = [downs + 1, downs, downs]
votes = [other_votes + 1, other_votes, other_votes + 1]
up_pct = [int( 100 * ups[i] / votes[i]) if votes[i] else "--" for i in range(len(votes))]
down_pct = [int( 100 * downs[i] / votes[i]) if votes[i] else "--" for i in range(len(votes))]
def controversy_text(_up_pct):
if isinstance(_up_pct, str):
return ""
p = abs(50 - _up_pct)
msg = "<b class='controversy%d'>%s</b>"
if p <= 5:
return msg % (3, _("quite controversial"))
elif p <= 15:
return msg % (2, _("controversial"))
elif p <= 25:
return msg % (1, _("uncontroversial"))
else:
return msg % (0, _("quite uncontroversial"))
controversy = map(controversy_text, up_pct)
%>
<script type="text/javascript">
function set_score(id, dir) {
for(var i = 0; i < 3; i++) {
var fn = (i == dir + 1) ? show: hide;
fn("down" + i + "_" + id);
fn("up" + i + "_" + id);
fn("controversy" + i + "_" + id);
}
}
</script>
<div class="container">
<ul>
<li class="selected">
${_("Vote on this article")}
</li>
<li>
<a href="${link}" target="_new">
%if thing.link:
${_("Discuss at the %(name)s reddit") % dict(name = c.site.name)}
%else:
${_("Submit to the %(name)s reddit") % dict(name = c.site.name)}
%endif
</a>
</li>
</ul>
<div class="votes ${'' if thing.link else 'disabled'}">
%for i in range(3):
<div class="right" id="controversy${i}_${fullname}"
${"" if i == dir + 1 else "style='display:none'"}>
${unsafe(controversy[i])}
</div>
%endfor
<a class="arrow up${'mod' if dir==1 else ''}"
id="up_${fullname}"
%if c.user_is_loggedin and thing.link:
href="#" onclick="mod('${fullname}', 1); return false; "
%else:
href="${submitlink}" target="_new"
%endif
>
%for i in range(3):
<span id="up${i}_${fullname}"
${"" if i == dir + 1 else "style='display:none'"}
><b>${up_pct[i]}%</b>&#32;liked it (${ups[i]})</span>
%endfor
</a>
<a class="arrow down${'mod' if dir==-1 else ''}" id="down_${fullname}"
%if c.user_is_loggedin and thing.link:
href="#" onclick="mod('${fullname}', 0); return false;"
%else:
href="${submitlink}" target="_new"
%endif
>
%for i in range(3):
<span id="down${i}_${fullname}"
${"" if i == dir + 1 else "style='display:none'"}
><b>${down_pct[i]}%</b>&#32;disliked it (${downs[i]})</span>
%endfor
</a>
</div>
<div class="clearleft"><!--IEsux--></div>
</div>
</div>
</%def>

View File

@@ -47,23 +47,63 @@
else:
arrow = "http://%s/static/widget_arrows.gif"
arrow = arrow % domain
expanded = request.get.get("expanded")
two_col = request.get.has_key("twocolumn") if l else False
%>
%if expanded:
<div class="reddit-voting-arrows"
${optionalstyle("float:left; margin: 1px;")}>
<script type="text/javascript">
var reddit_bordercolor="FFFFFF";
</script>
<%
url = "http://%s/button_content?t=4&id=%s" % (get_domain(cname = c.cname, subreddit = True), thing._fullname)
if c.bgcolor:
url += "&bgcolor=%s&bordercolor=%s" % (c.bgcolor, c.bgcolor)
else:
url += "&bgcolor=FFFFFF&bordercolor=FFFFFF"
%>
<iframe src="${url}" height="55" width="51" scrolling="no" frameborder="0"
${optionalstyle("margin:0px;")}>
</iframe>
</div>
%else:
<a href="${permalink}" class="reddit-voting-arrows" target="_blank"
${optionalstyle("float:left; display:block;")}>
<img src="${arrow}" alt="vote" ${optionalstyle("border:none;")}/>
<img src="${arrow}" alt="vote" ${optionalstyle("border:none;margin-top:3px;")}/>
</a>
<div class="reddit-entry" ${optionalstyle("margin-left: 20px; min-height:32px;padding-bottom:5px;")}>
%endif
<div class="reddit-entry"
%if expanded:
${optionalstyle("margin-left: 58px;")}
%else:
${optionalstyle("margin-left: 20px; min-height:32px;")}
%endif
>
<a href="${thing.url}" class="reddit-link-title"
${optionalstyle("text-decoration:none;color:#336699;")}>
${optionalstyle("text-decoration:none;color:#336699;font-size:small;")}>
${thing.title}
</a>
<br />
<small ${optionalstyle("color:gray;")}>
%if not expanded:
<br />
%endif
<small
%if expanded:
${optionalstyle("color:gray;margin-left:5px;")}
%else:
${optionalstyle("color:gray;")}
%endif
>
%if not expanded:
${thing.score} ${ungettext("point", "points", thing.score)}
|&#32;
%endif
<a class="reddit-comment-link"
${optionalstyle("color:gray")}
href="${permalink}">${com_label}</a>
</small>
</div>
<div class="reddit-link-end" ${optionalstyle("clear:left; padding:3px;")}>
<!--IE6sux-->
</div>
</%def>

View File

@@ -36,11 +36,11 @@
%if two_col:
%if i == 0:
<div class="reddit-listing-left"
${optionalstyle("float:left;width:43%")}>
${optionalstyle("float:left;width:47%")}>
%elif i - 1 < (l+1)/2 and i >= (l+1)/2:
</div>
<div class="reddit-listing-right"
${optionalstyle("float:right; width:43%;")}>
${optionalstyle("float:right; width:49%;")}>
%endif
%endif

View File

@@ -0,0 +1,84 @@
<div class="instructions socialite">
<h1>install Socialite, a reddit Firefox extension</h1>
<p class="logotext">
<img src="/static/socialite/socialite.png" alt="Socialite logo" class="logo"/>
Socialite integrates the features of reddit into Firefox.
</p>
<p class="logoclear">
When you click on links on reddit, Socialite displays a toolbar above the page, allowing you to vote articles up and down, view comments, and save links to your profile. Features include:
</p>
<div class="features">
<p class="buttonclear">
<a class="installbutton" href="http://addons.reddit.com/socialite/socialite.xpi">
<span>Add to Firefox</span>
</a>
</p>
<ul>
<li>simple like reddit</li>
<li>vote, save, and hide links using the toolbar</li>
<li>look up sites on reddit with a single click</li>
<li>meditate on those clever titles without leaving the page</li>
</ul>
</div>
<h2>how to use it</h2>
<p>
Socialite will display a toolbar automatically when you click on reddit links.</p>
<p class="screenshot">
<img src="/static/socialite/demopic.png" alt="Socialite screenshot"/>
</p>
<p>
In addition, you can open the bar manually by clicking on the reddit
icon on the right side of your location bar:
</p>
<p class="screenshot">
<img src="/static/socialite/losbutton.png" alt="lookup-or-submit button"/>
</p>
<p>
If the page is not submitted to reddit, or you click again, a submit
bar will appear:
</p>
<p class="screenshot">
<img src="/static/socialite/submitpic.png" alt="submit bar screenshot"/>
</p>
<p>
(<b>HINT:</b>&#32;if you want to skip straight to the submit bar,
middle-click on the reddit icon.)
</p>
<h2>Configuration</h2>
<p>
you can configure what buttons are displayed in the toolbar in the
extensions preferences:
</p>
<p class="screenshot">
<img src="/static/socialite/siteproperties.png" alt="site properties window screenshot"/>
</p>
<h2>configure for other reddit sites</h2>
<p>
Since reddit lets you
&#32;<a href="http://blog.reddit.com/2008/08/now-you-can-restyle-and-host-your.html">
host reddits from other domains</a>, like
&#32;<a href="http://www.baconbuzz.com/">BaconBuzz</a>, Socialite will also let you edit the list of domains that it works for.
</p>
<p class="screenshot">
<img src="/static/socialite/sitepreferences.png"
alt="preferences window screenshot"/>
</p>
</div>

View File

@@ -48,6 +48,9 @@ function update() {
if (which == "all") {
url = "http://${sr_domain}/" + f.what.value + "/.embed?limit=" +
f.num.value + "&t=" + f.when.value;
if(f.what.value == "new") {
url += "&sort=new";
}
} else if (which == "one") {
if (!f.who.value) return;
url = "http://${domain}/user/"+f.who.value+"/"+
@@ -62,6 +65,9 @@ function update() {
alert(which);
}
$("preview").style.width = "";
if(f.expanded.checked) {
url += "&expanded=1";
}
if(f.nostyle.checked) {
url += "&style=off";
hide("css-options");
@@ -76,7 +82,7 @@ function update() {
}
if(f.twocol.checked) {
url += "&twocolumn=true";
$("preview").style.width = "40em";
$("preview").style.width = "550px";
}
}
@@ -96,7 +102,7 @@ function update() {
<div id="preview">
<span>preview</span>
<div id="previewbox">
<script src="http://${domain}/.embed?limit=5" type="text/javascript"></script>
<script src="http://${sr_domain}/.embed?limit=5" type="text/javascript"></script>
</div>
</div>
@@ -196,6 +202,17 @@ function update() {
</span>
</label>
</p>
<p>
<input name="expanded" id="expanded" type="checkbox"
onfocus="update()"
onchange="update()"/>
<label for="expanded">
${_("enable in-widget voting")}
&#32;<span class="little gray">
${_("(will slow down the rendering)")}
</span>
</label>
</p>
<div id="css-options">
<p>
<input name="twocol" id="twocol" type="checkbox"