UX: Change category badge style to use stripes

This commit is contained in:
Robin Ward 2015-01-20 11:36:28 -05:00
parent f3c9310e12
commit 350554e198
27 changed files with 175 additions and 211 deletions

View File

@ -1,11 +1,5 @@
/**
Renders a drop down for selecting a category
var get = Ember.get;
@class CategoryDropComponent
@extends Ember.Component
@namespace Discourse
@module Discourse
**/
export default Ember.Component.extend({
classNameBindings: ['category::no-category', 'categories:has-drop'],
tagName: 'li',
@ -44,11 +38,20 @@ export default Ember.Component.extend({
badgeStyle: function() {
var category = this.get('category');
if (category) {
return Discourse.HTML.categoryStyle(category);
} else {
return "background-color: #eee; color: #333";
var color = get(category, 'color'),
textColor = get(category, 'text_color');
if (color || textColor) {
var style = "";
if (color) { style += "background-color: #" + color + "; "; }
if (textColor) { style += "color: #" + textColor + "; "; }
return style;
}
}
return "background-color: #eee; color: #333";
}.property('category'),
clickEventName: function() {

View File

@ -1,3 +1,5 @@
import { categoryBadgeHTML } from 'discourse/helpers/category-link';
export default Ember.Component.extend({
_initializeAutocomplete: function(){
@ -25,7 +27,7 @@ export default Ember.Component.extend({
},
template: template,
transformComplete: function(category) {
return Discourse.HTML.categoryBadge(category, {allowUncategorized: true});
return categoryBadgeHTML(category, {allowUncategorized: true});
}
});
}.on('didInsertElement')

View File

@ -1,5 +1,6 @@
import ModalFunctionality from 'discourse/mixins/modal-functionality';
import ObjectController from 'discourse/controllers/object';
import { categoryBadgeHTML } from 'discourse/helpers/category-link';
// Modal for editing / creating a category
export default ObjectController.extend(ModalFunctionality, {
@ -69,7 +70,7 @@ export default ObjectController.extend(ModalFunctionality, {
parent_category_id: parseInt(this.get('parent_category_id'),10),
read_restricted: this.get('model.read_restricted')
});
return Discourse.HTML.categoryBadge(c, {showParent: true, link: false});
return categoryBadgeHTML(c, {link: false});
}.property('parent_category_id', 'categoryName', 'color', 'text_color'),
// background colors are available as a pipe-separated string

View File

@ -1,5 +1,6 @@
import ModalFunctionality from 'discourse/mixins/modal-functionality';
import ObjectController from 'discourse/controllers/object';
import { categoryBadgeHTML } from 'discourse/helpers/category-link';
// This controller handles displaying of history
export default ObjectController.extend(ModalFunctionality, {
@ -22,14 +23,14 @@ export default ObjectController.extend(ModalFunctionality, {
hide: function(postId, postVersion) {
var self = this;
Discourse.Post.hideRevision(postId, postVersion).then(function (result) {
Discourse.Post.hideRevision(postId, postVersion).then(function () {
self.refresh(postId, postVersion);
});
},
show: function(postId, postVersion) {
var self = this;
Discourse.Post.showRevision(postId, postVersion).then(function (result) {
Discourse.Post.showRevision(postId, postVersion).then(function () {
self.refresh(postId, postVersion);
});
},
@ -68,7 +69,7 @@ export default ObjectController.extend(ModalFunctionality, {
var changes = this.get("category_changes");
if (changes) {
var category = Discourse.Category.findById(changes["previous"]);
return Discourse.HTML.categoryBadge(category, { allowUncategorized: true });
return categoryBadgeHTML(category, { allowUncategorized: true });
}
}.property("category_changes"),
@ -76,12 +77,12 @@ export default ObjectController.extend(ModalFunctionality, {
var changes = this.get("category_changes");
if (changes) {
var category = Discourse.Category.findById(changes["current"]);
return Discourse.HTML.categoryBadge(category, { allowUncategorized: true });
return categoryBadgeHTML(category, { allowUncategorized: true });
}
}.property("category_changes"),
wiki_diff: function() {
var changes = this.get("wiki_changes")
var changes = this.get("wiki_changes");
if (changes) {
return changes["current"] ?
'<span class="fa-stack"><i class="fa fa-pencil-square-o fa-stack-2x"></i></span>' :
@ -93,7 +94,7 @@ export default ObjectController.extend(ModalFunctionality, {
var moderator = Discourse.Site.currentProp('post_types.moderator_action');
var changes = this.get("post_type_changes");
if (changes) {
return changes["current"] == moderator ?
return changes["current"] === moderator ?
'<span class="fa-stack"><i class="fa fa-shield fa-stack-2x"></i></span>' :
'<span class="fa-stack"><i class="fa fa-shield fa-stack-2x"></i><i class="fa fa-ban fa-stack-2x"></i></span>';
}

View File

@ -1,4 +1,63 @@
import registerUnbound from 'discourse/helpers/register-unbound';
import { iconHTML } from 'discourse/helpers/fa-icon';
var get = Em.get,
escapeExpression = Handlebars.Utils.escapeExpression;
function categoryStripe(tagName, category, extraClasses, href) {
if (!category) { return ""; }
var color = Em.get(category, 'color'),
style = color ? "style='background-color: #" + color + ";'" : "";
return "<" + tagName + " class='badge-category-parent" + extraClasses + "' " + style + " href=\"" + href + "\"></" + tagName + ">";
}
export function categoryBadgeHTML(category, opts) {
opts = opts || {};
if ((!category) ||
(!opts.allowUncategorized &&
Em.get(category, 'id') === Discourse.Site.currentProp("uncategorized_category_id") &&
Discourse.SiteSettings.suppress_uncategorized_badge
)
) return "";
var description = get(category, 'description_text'),
restricted = get(category, 'read_restricted'),
url = Discourse.getURL("/c/") + Discourse.Category.slugFor(category),
href = (opts.link === false ? '' : url),
tagName = (opts.link === false || opts.link === "false" ? 'span' : 'a'),
extraClasses = (opts.extraClasses ? (' ' + opts.extraClasses) : '');
var html = "";
var parentCat = Discourse.Category.findById(category.get('parent_category_id'));
if (opts.hideParent) { parentCat = null; }
html += categoryStripe(tagName, parentCat, extraClasses, href);
if (parentCat !== category) {
html += categoryStripe(tagName, category, extraClasses, href);
}
var classNames = "badge-category clear-badge" + extraClasses;
if (restricted) { classNames += " restricted"; }
html += "<" + tagName + ' href="' + href + '" ' +
'data-drop-close="true" class="' + classNames + '"' +
(description ? 'title="' + escapeExpression(description) + '" ' : '') +
">";
var name = escapeExpression(get(category, 'name'));
if (restricted) {
html += "<div>" + iconHTML('lock') + " " + name + "</div>";
} else {
html += name;
}
html += "</" + tagName + ">";
return "<span class='badge-wrapper'>" + html + "</span>";
}
export function categoryLinkHTML(category, options) {
var categoryOptions = {};
@ -9,12 +68,11 @@ export function categoryLinkHTML(category, options) {
if (options) {
if (options.allowUncategorized) { categoryOptions.allowUncategorized = true; }
if (options.showParent) { categoryOptions.showParent = true; }
if (options.onlyStripe) { categoryOptions.onlyStripe = true; }
if (options.link !== undefined) { categoryOptions.link = options.link; }
if (options.extraClasses) { categoryOptions.extraClasses = options.extraClasses; }
if (options.hideParent) { categoryOptions.hideParent = true; }
}
return new Handlebars.SafeString(Discourse.HTML.categoryBadge(category, categoryOptions));
return new Handlebars.SafeString(categoryBadgeHTML(category, categoryOptions));
}
registerUnbound('category-link', categoryLinkHTML);

View File

@ -1,11 +1,3 @@
/**
Helpers to build HTML strings as well as custom fragments.
@class HTML
@namespace Discourse
@module Discourse
**/
var customizations = {};
Discourse.HTML = {
@ -15,9 +7,6 @@ Discourse.HTML = {
using `setCustomHTML(key, html)`. This is used by a handlebars helper to find
the HTML content it wants. It will also check the `PreloadStore` for any server
side preloaded HTML.
@method getCustomHTML
@param {String} key to lookup
**/
getCustomHTML: function(key) {
var c = customizations[key];
@ -31,104 +20,9 @@ Discourse.HTML = {
}
},
/**
Set a fragment of HTML by key. It can then be looked up with `getCustomHTML(key)`.
@method setCustomHTML
@param {String} key to store the html
@param {String} html fragment to store
**/
// Set a fragment of HTML by key. It can then be looked up with `getCustomHTML(key)`.
setCustomHTML: function(key, html) {
customizations[key] = html;
},
/**
Returns the CSS styles for a category
@method categoryStyle
@param {Discourse.Category} category the category whose link we want
**/
categoryStyle: function(category) {
var color = Em.get(category, 'color'),
textColor = Em.get(category, 'text_color');
if (!color && !textColor) { return; }
// Add the custom style if we need to
var style = "";
if (color) { style += "background-color: #" + color + "; "; }
if (textColor) { style += "color: #" + textColor + "; "; }
return style;
},
/**
Create a category badge
@method categoryBadge
@param {Discourse.Category} category the category whose link we want
@param {Object} opts The options for the category link
@param {Boolean} opts.allowUncategorized Whether we allow rendering of the uncategorized category (default false)
@param {Boolean} opts.showParent Whether to visually show whether category is a sub-category (default false)
@param {Boolean} opts.link Whether this category badge should link to the category (default true)
@param {String} opts.extraClasses add this string to the class attribute of the badge
@returns {String} the html category badge
**/
categoryBadge: function(category, opts) {
opts = opts || {};
if ((!category) ||
(!opts.allowUncategorized &&
Em.get(category, 'id') === Discourse.Site.currentProp("uncategorized_category_id") &&
Discourse.SiteSettings.suppress_uncategorized_badge
)
) return "";
var name = Em.get(category, 'name'),
description = Em.get(category, 'description_text'),
restricted = Em.get(category, 'read_restricted'),
url = Discourse.getURL("/c/") + Discourse.Category.slugFor(category),
elem = (opts.link === false ? 'span' : 'a'),
extraClasses = (opts.extraClasses ? (' ' + opts.extraClasses) : ''),
html = "<" + elem + " href=\"" + (opts.link === false ? '' : url) + "\" ",
categoryStyle;
// Parent stripe implies onlyStripe
if (opts.onlyStripe) { opts.showParent = true; }
html += "data-drop-close=\"true\" class=\"badge-category" + (restricted ? ' restricted' : '' ) +
(opts.onlyStripe ? ' clear-badge' : '') +
extraClasses + "\" ";
name = Handlebars.Utils.escapeExpression(name);
// Add description if we have it, without tags. Server has sanitized the description value.
if (description) html += "title=\"" + Handlebars.Utils.escapeExpression(description) + "\" ";
if (!opts.onlyStripe) {
categoryStyle = Discourse.HTML.categoryStyle(category);
if (categoryStyle) {
html += "style=\"" + categoryStyle + "\" ";
}
}
if (restricted) {
html += "><div><i class='fa fa-lock'></i> " + name + "</div></" + elem + ">";
} else {
html += ">" + name + "</" + elem + ">";
}
if (opts.onlyStripe || (opts.showParent && category.get('parent_category_id'))) {
var parent = Discourse.Category.findById(category.get('parent_category_id'));
if (!parent) { parent = category; }
categoryStyle = Discourse.HTML.categoryStyle(opts.onlyStripe ? category : parent) || '';
html = "<span class='badge-wrapper'><" + elem + " class='badge-category-parent" + extraClasses + "' style=\"" + categoryStyle +
"\" href=\"" + (opts.link === false ? '' : url) + "\"><span class='category-name'>" +
(Em.get(parent, 'read_restricted') ? "<i class='fa fa-lock'></i> " : "") +
Em.get(parent, 'name') + "</span></" + elem + ">" +
html + "</span>";
}
return html;
}
};

View File

@ -232,6 +232,7 @@ Discourse.Category.reopenClass({
},
findById: function(id) {
if (!id) { return; }
return Discourse.Category.idMap()[id];
},

View File

@ -1,7 +1,7 @@
<div class='autocomplete'>
<ul>
{{#each option in options}}
<li>{{category-link option allowUncategorized="true"}}</li>
<li>{{category-link option allowUncategorized="true" link="false"}}</li>
{{/each}}
</ul>
</div>

View File

@ -1,27 +1,27 @@
{{#if category}}
<a href="#" {{action "expand"}} class="badge-category" {{bind-attr style="badgeStyle"}}>
<a href {{action "expand"}} class="badge-category" {{bind-attr style="badgeStyle"}}>
{{#if category.read_restricted}}
<i class='fa fa-lock'></i>
{{fa-icon "lock"}}
{{/if}}
{{category.name}}
</a>
{{else}}
{{#if noSubcategories}}
<a href='#' {{action "expand"}} class='badge-category home' {{bind-attr style="badgeStyle"}}>{{i18n 'categories.no_subcategory'}}</a>
<a href {{action "expand"}} class='badge-category home' {{bind-attr style="badgeStyle"}}>{{i18n 'categories.no_subcategory'}}</a>
{{else}}
<a href='#' {{action "expand"}} class='badge-category home' {{bind-attr style="badgeStyle"}}>{{allCategoriesLabel}}</a>
<a href {{action "expand"}} class='badge-category home' {{bind-attr style="badgeStyle"}}>{{allCategoriesLabel}}</a>
{{/if}}
{{/if}}
{{#if categories}}
<a href='#' {{action "expand"}} {{bind-attr class="dropdownButtonClass" style="badgeStyle"}}><i {{bind-attr class="iconClass"}}></i></a>
<a href {{action "expand"}} {{bind-attr class="dropdownButtonClass" style="badgeStyle"}}><i {{bind-attr class="iconClass"}}></i></a>
<section {{bind-attr class="expanded::hidden :category-dropdown-menu"}} class='chooser'>
<div class='cat'><a {{bind-attr href=allCategoriesUrl}} data-drop-close="true" class='badge-category home'>{{allCategoriesLabel}}</a></div>
{{#if subCategory}}
<div class='cat'><a {{bind-attr href=noCategoriesUrl}} data-drop-close="true" class='badge-category home'>{{i18n 'categories.no_subcategory'}}</a></div>
<div class='cat'><a {{bind-attr href=noCategoriesUrl}} data-drop-close="true" class='badge-category home'>{{i18n 'categories.no_subcategory'}}</a></div>
{{/if}}
{{#if renderCategories}}
{{#each c in categories}}<div class='cat'>{{category-link c allowUncategorized=true}}</div>{{/each}}
{{#each c in categories}}<div class='cat'>{{category-link c allowUncategorized=true hideParent=subCategory}}</div>{{/each}}
{{/if}}
</section>
{{/if}}

View File

@ -32,7 +32,7 @@
{{#if c.subcategories}}
<div class='subcategories'>
{{#each s in c.subcategories}}
{{category-link s showParent="true" onlyStripe="true"}}
{{category-link s hideParent="true"}}
{{#if s.unreadTopics}}
<a href={{unbound s.unreadUrl}} class='badge new-posts badge-notification' title='{{i18n 'topic.unread_topics' count=s.unreadTopics}}'>{{unbound s.unreadTopics}}</a>
{{/if}}

View File

@ -113,9 +113,9 @@
{{/if}}
</h1>
{{#if topic.category.parentCategory}}
{{bound-category-link topic.category.parentCategory onlyStripe="true"}}
{{bound-category-link topic.category.parentCategory}}
{{/if}}
{{bound-category-link topic.category onlyStripe="true"}}
{{bound-category-link topic.category hideParent=true}}
</div>
</div>
</div>

View File

@ -1 +1 @@
<td class='category'>{{category-link category showParent="true"}}</td>
<td class='category'>{{category-link category}}</td>

View File

@ -32,7 +32,7 @@
</div>
{{#unless controller.hideCategory}}
<div class='category'>
{{category-link t.category showParent="true"}}
{{category-link t.category}}
</div>
{{/unless}}
{{#if controller.showParticipants}}

View File

@ -46,7 +46,7 @@
<td>
<div class='subcategories'>
{{#each subcategory in c.subcategories}}
{{category-link subcategory showParent="true"}}
{{category-link subcategory}}
{{/each}}
</div>
</td>

View File

@ -11,7 +11,7 @@
<div class="topic-item-stats clearfix">
{{#unless controller.hideCategory}}
<div class='category'>
{{category-link content.category showParent="true"}}
{{category-link content.category}}
</div>
{{/unless}}

View File

@ -15,7 +15,7 @@
{{#if subCategories}}
<label>{{i18n 'categories.subcategories'}}</label>
{{#each s in subCategories}}
{{category-badge s}}
{{category-badge s hideParent="true"}}
{{/each}}
{{else}}
<label>{{i18n 'category.parent'}}</label>

View File

@ -46,7 +46,7 @@
{{#each c in categories itemController='site-map-category'}}
<li class="category">
{{category-link c allowUncategorized="true" showParent="true"}}
{{category-link c allowUncategorized="true"}}
{{#if c.unreadTotal}}
<a href={{unbound c.url}} class='badge badge-notification'>{{c.unreadTotal}}</a>

View File

@ -46,7 +46,7 @@
{{#if category.parentCategory}}
{{bound-category-link category.parentCategory}}
{{/if}}
{{bound-category-link category}}
{{bound-category-link category hideParent=true}}
{{plugin-outlet "topic-category"}}
{{/unless}}
{{/if}}

View File

@ -1,6 +1,5 @@
import ComboboxView from 'discourse/views/combo-box';
var badgeHtml = Discourse.HTML.categoryBadge;
import { categoryBadgeHTML } from 'discourse/helpers/category-link';
export default ComboboxView.extend({
classNames: ['combobox category-combobox'],
@ -57,10 +56,10 @@ export default ComboboxView.extend({
}
if (!category) return item.text;
var result = badgeHtml(category, {showParent: false, link: false, allowUncategorized: true}),
var result = categoryBadgeHTML(category, {link: false, allowUncategorized: true, hideParent: true}),
parentCategoryId = category.get('parent_category_id');
if (parentCategoryId) {
result = badgeHtml(Discourse.Category.findById(parentCategoryId), {link: false}) + "&nbsp;" + result;
result = categoryBadgeHTML(Discourse.Category.findById(parentCategoryId), {link: false}) + "&nbsp;" + result;
}
result += " <span class='topic-count'>&times; " + category.get('topic_count') + "</span>";

View File

@ -1,5 +1,6 @@
import AddCategoryClass from 'discourse/mixins/add-category-class';
import { listenForViewEvent } from 'discourse/lib/app-events';
import { categoryBadgeHTML } from 'discourse/helpers/category-link';
var TopicView = Discourse.View.extend(AddCategoryClass, Discourse.Scrolling, {
templateName: 'topic',
@ -130,7 +131,7 @@ var TopicView = Discourse.View.extend(AddCategoryClass, Discourse.Scrolling, {
}
if (category) {
opts.catLink = Discourse.HTML.categoryBadge(category, {showParent: true});
opts.catLink = categoryBadgeHTML(category);
} else {
opts.catLink = "<a href=\"" + Discourse.getURL("/categories") + "\">" + I18n.t("topic.browse_all_categories") + "</a>";
}

View File

@ -154,9 +154,9 @@
}
.list-controls {
.home {
background-color: scale-color-diff();
.category-dropdown-menu .home {
color: $primary;
margin-left: 8px;
}
.badge-category {
padding: 4px 10px;
@ -164,6 +164,10 @@
line-height: 24px;
float: left;
}
.category-dropdown-menu .badge-category {
width: 100%;
}
.category-dropdown-button {
border-left: 1px solid rgba(0,0,0,0.15);
font-size: 1.143em;
@ -223,18 +227,21 @@ ol.category-breadcrumb {
background-color: $secondary;
z-index: 100;
.cat {
margin-right: 20px;
}
a.badge-category, a.badge-category-parent {
line-height: 19px;
overflow:hidden;
margin-bottom: 0;
}
a.badge-category {
font-size: 0.929em;
font-weight: bold;
float: none;
line-height: 19px;
text-transform: none;
width: 100%;
min-width: 102px;
margin-right: 20px;
margin-bottom: 0;
max-width:200px;
overflow:hidden;
text-overflow:ellipsis;
}
}

View File

@ -28,9 +28,9 @@
.badge-category {
padding: 6px;
color: $secondary;
color: $primary;
&[href] {
color: $secondary;
color: $primary;
}
}

View File

@ -402,6 +402,9 @@
.user-stream {
.category {
margin-left: 3px;
}
.excerpt {
margin: 5px 0;
font-size: 0.929em;

View File

@ -71,15 +71,8 @@ module UserNotificationsHelper
category_url = "#{Discourse.base_url}#{category.url}"
if opts[:only_stripe]
result << "<a href='#{category_url}' style='background-color: ##{category.color}; font-size: 12px; padding: 2px 1px; font-weight: bold; margin: 0; width: 2px; white-space:nowrap;'>&nbsp;</a>"
result << "<a href='#{category_url}' style='font-size: 12px; font-weight: bold; margin-left: 3px; color: #222;'>#{category.name}</a>"
else
if category.parent_category.present?
result << "<a href='#{category_url}' style='background-color: ##{category.parent_category.color}; font-size: 12px; padding: 4px 2px; font-weight: bold; margin: 0; width: 2px; white-space:nowrap;'>&nbsp;</a>"
end
result << "<a href='#{category_url}' style='background-color: ##{category.color}; color: ##{category.text_color}; font-size: 12px; padding: 4px 6px; font-weight: bold; margin: 0; white-space:nowrap;'>#{category.name}</a>"
end
result << "<a href='#{category_url}' style='background-color: ##{category.color}; font-size: 12px; padding: 2px 1px; font-weight: bold; margin: 0; width: 2px; white-space:nowrap;'>&nbsp;</a>"
result << "<a href='#{category_url}' style='font-size: 12px; font-weight: bold; margin-left: 3px; color: #222;'>#{category.name}</a>"
result.html_safe
end

View File

@ -45,7 +45,7 @@
<li>
<%= link_to t.title, "#{Discourse.base_url}#{t.relative_url}" %>
<span class='post-count'><%= t('user_notifications.digest.posts', count: t.posts_count) %></span>
<%= email_category(t.category, only_stripe: true) %>
<%= email_category(t.category) %>
</li>
</ul>
<%- end -%>

View File

@ -0,0 +1,41 @@
module("categoryBadgeHTML");
import { categoryBadgeHTML } from "discourse/helpers/category-link";
test("categoryBadge without a category", function() {
blank(categoryBadgeHTML(), "it returns no HTML");
});
test("Regular categoryBadge", function() {
var category = Discourse.Category.create({
name: 'hello',
id: 123,
description_text: 'cool description',
color: 'ff0',
text_color: 'f00'
}),
tag = parseHTML(categoryBadgeHTML(category))[0];
equal(tag.name, 'span', 'it creates a `span` wrapper tag');
equal(tag.attributes['class'], 'badge-wrapper', 'it has the correct class');
var label = tag.children[1];
equal(label.attributes.title, 'cool description', 'it has the correct title');
equal(label.children[0].data, 'hello', 'it has the category name');
});
test("undefined color", function() {
var noColor = Discourse.Category.create({ name: 'hello', id: 123 }),
tag = parseHTML(categoryBadgeHTML(noColor))[0];
blank(tag.attributes.style, "it has no color style because there are no colors");
});
test("allowUncategorized", function() {
var uncategorized = Discourse.Category.create({name: 'uncategorized', id: 345});
sandbox.stub(Discourse.Site, 'currentProp').withArgs('uncategorized_category_id').returns(345);
blank(categoryBadgeHTML(uncategorized), "it doesn't return HTML for uncategorized by default");
present(categoryBadgeHTML(uncategorized, {allowUncategorized: true}), "it returns HTML");
});

View File

@ -2,46 +2,6 @@ module("Discourse.HTML");
var html = Discourse.HTML;
test("categoryBadge without a category", function() {
blank(html.categoryBadge(), "it returns no HTML");
});
test("Regular categoryBadge", function() {
var category = Discourse.Category.create({
name: 'hello',
id: 123,
description_text: 'cool description',
color: 'ff0',
text_color: 'f00'
}),
tag = parseHTML(html.categoryBadge(category))[0];
equal(tag.name, 'a', 'it creates an `a` tag');
equal(tag.attributes['class'], 'badge-category', 'it has the correct class');
equal(tag.attributes.title, 'cool description', 'it has the correct title');
ok(tag.attributes.style.indexOf('#ff0') !== -1, "it has the color style");
ok(tag.attributes.style.indexOf('#f00') !== -1, "it has the textColor style");
equal(tag.children[0].data, 'hello', 'it has the category name');
});
test("undefined color", function() {
var noColor = Discourse.Category.create({ name: 'hello', id: 123 }),
tag = parseHTML(html.categoryBadge(noColor))[0];
blank(tag.attributes.style, "it has no color style because there are no colors");
});
test("allowUncategorized", function() {
var uncategorized = Discourse.Category.create({name: 'uncategorized', id: 345});
sandbox.stub(Discourse.Site, 'currentProp').withArgs('uncategorized_category_id').returns(345);
blank(html.categoryBadge(uncategorized), "it doesn't return HTML for uncategorized by default");
present(html.categoryBadge(uncategorized, {allowUncategorized: true}), "it returns HTML");
});
test("customHTML", function() {
blank(html.getCustomHTML('evil'), "there is no custom HTML for a key by default");