diff --git a/r2/r2/controllers/api.py b/r2/r2/controllers/api.py
index 748e7f3b3..7cc065076 100644
--- a/r2/r2/controllers/api.py
+++ b/r2/r2/controllers/api.py
@@ -2076,8 +2076,9 @@ class ApiController(RedditController):
@validatedForm(VUser(),
VModhash(),
- flair_template_id = nop("flair_template_id"))
- def POST_selectflair(self, form, jquery, flair_template_id):
+ flair_template_id = nop("flair_template_id"),
+ text = VFlairText("text"))
+ def POST_selectflair(self, form, jquery, flair_template_id, text):
flair_template = FlairTemplateBySubredditIndex.get_template(
c.site._id, flair_template_id)
@@ -2092,7 +2093,14 @@ class ApiController(RedditController):
g.log.debug('flair self-assignment not permitted')
return
- text = flair_template.text
+ # Ignore given text if user doesn't have permission to customize it.
+ if (not c.site.is_moderator(c.user) and not c.user_is_admin
+ and not flair_template.text_editable):
+ text = None
+
+ if not text:
+ text = flair_template.text
+
css_class = flair_template.css_class
c.site.add_flair(c.user)
diff --git a/r2/r2/lib/pages/pages.py b/r2/r2/lib/pages/pages.py
index 6b1de74cc..fec289442 100644
--- a/r2/r2/lib/pages/pages.py
+++ b/r2/r2/lib/pages/pages.py
@@ -2563,7 +2563,6 @@ class FlairSelector(CachedTemplate):
css_class = getattr(c.user, attr_pattern % 'css_class', '')
ids = FlairTemplateBySubredditIndex.get_template_ids(c.site._id)
- # TODO(intortus): Maintain sorting.
templates = FlairTemplate._byID(ids).values()
for template in templates:
if template.covers((text, css_class)):
@@ -2572,9 +2571,23 @@ class FlairSelector(CachedTemplate):
else:
matching_template = None
- choices = [WrappedUser(c.user, subreddit=c.site, force_show_flair=True,
- flair_template=template)
- for template in templates]
+ all_text_editable = bool(c.user_is_admin or c.site.is_moderator(c.user))
+
+ choices = [
+ WrappedUser(
+ c.user, subreddit=c.site, force_show_flair=True,
+ flair_template=template,
+ flair_text_editable=all_text_editable or template.text_editable)
+ for template in templates]
+
+ # If one of the templates is already selected, modify its text to match
+ # the user's current flair.
+ if matching_template:
+ for choice in choices:
+ if choice.flair_template_id == matching_template:
+ if choice.flair_text_editable:
+ choice.flair_text = text
+ break
wrapped_user = WrappedUser(c.user, subreddit=c.site,
force_show_flair=True)
diff --git a/r2/r2/public/static/css/reddit.css b/r2/r2/public/static/css/reddit.css
index 62056441c..85eec8e4d 100644
--- a/r2/r2/public/static/css/reddit.css
+++ b/r2/r2/public/static/css/reddit.css
@@ -713,6 +713,15 @@ ul.flat-vert {text-align: left;}
.flairselector li a:hover { text-decoration: none; }
.flairselector li.selected { border: dashed 1px black; }
+.flairselector form {
+ clear: both;
+ text-align: center;
+}
+
+.flairselector .customizer { display: none; }
+.flairselector .customizer.texteditable { display: inline-block; }
+.flairselector .customizer input { display: block; }
+
.media-button .option { color: red; }
.media-button .option.active {
background: transparent none no-repeat scroll right center;
diff --git a/r2/r2/public/static/js/flair.js b/r2/r2/public/static/js/flair.js
index 7302f1aef..a17fbdf4d 100644
--- a/r2/r2/public/static/js/flair.js
+++ b/r2/r2/public/static/js/flair.js
@@ -29,6 +29,26 @@ $(function() {
return false;
}
+ function selectFlairInSelector(e) {
+ $(".flairselector li").removeClass("selected");
+ $(this).addClass("selected");
+ var form = $(this).parent().parent().siblings("form").get(0);
+ $(form).children('input[name="flair_template_id"]').val(this.id);
+ var customizer = $(form).children(".customizer");
+ if ($(this).hasClass("texteditable")) {
+ customizer.addClass("texteditable");
+ var input = customizer.children("input");
+ input.val($.trim($(this).children(".flair").text())).select();
+ input.keyup(function() {
+ $(".flairselection .flair").text($(input).val());
+ });
+ } else {
+ customizer.removeClass("texteditable");
+ }
+ $(".flairselection").html($(this).first().children().clone());
+ return false;
+ }
+
function postFlairSelection(e) {
$(this).parent().parent().siblings("input").val(this.id);
post_form(this.parentNode.parentNode.parentNode, "selectflair");
@@ -39,9 +59,11 @@ $(function() {
var button = this;
function columnize(col) {
+ var min_cols = 2;
var max_col_height = 10;
var length = $(col).children().length;
- var num_cols = Math.ceil(length / max_col_height);
+ var num_cols =
+ Math.max(min_cols, Math.ceil(length / max_col_height));
var height = Math.ceil(length / num_cols);
var num_short_cols = num_cols * height - length;
@@ -67,7 +89,11 @@ $(function() {
.css("left",
($(button).position().left + $(button).width() - width)
+ "px");
- $(".flairselector li:not(.error)").click(postFlairSelection);
+ $(".flairselector li:not(.error)").click(selectFlairInSelector);
+ $(".flairselector").click(function(e) { return false; });
+ $(".flairselector form")
+ .click(function(e) { e.stopPropagation(); });
+ $(".flairselector form").submit(postFlairSelection);
}
$(".flairselector").html('
');
diff --git a/r2/r2/templates/flairlistrow.html b/r2/r2/templates/flairlistrow.html
index 233f331e2..3edd8a09e 100644
--- a/r2/r2/templates/flairlistrow.html
+++ b/r2/r2/templates/flairlistrow.html
@@ -41,7 +41,7 @@ from r2.lib.pages import WrappedUser
-
+
${utils.error_field(('BAD_CSS_NAME', 'flair_css_class'), 'name')}
${utils.error_field(('TOO_MUCH_FLAIR_CSS', 'flair_css_class'), 'name')}
diff --git a/r2/r2/templates/flairprefs.html b/r2/r2/templates/flairprefs.html
index 18ed1bb0a..ff8dd23ba 100644
--- a/r2/r2/templates/flairprefs.html
+++ b/r2/r2/templates/flairprefs.html
@@ -22,7 +22,6 @@
%if thing.sr_flair_enabled: