diff --git a/client/css/forms.styl b/client/css/forms.styl
index bb4c96fc..1f58c3e6 100644
--- a/client/css/forms.styl
+++ b/client/css/forms.styl
@@ -1,3 +1,4 @@
+@import mixins
@import colors
form
@@ -252,7 +253,7 @@ div.tag-input
color: $inactive-link-color
margin-left: 0.7em
font-size: 90%
-
+ unselectable()
ul.compact-tags
line-height: 130%
@@ -265,6 +266,7 @@ ul.compact-tags
color: $inactive-link-color
margin-left: 0.7em
font-size: 90%
+ unselectable()
div.tag-relations
font-size: 80%
diff --git a/client/css/main.styl b/client/css/main.styl
index b290c78f..0907caa1 100644
--- a/client/css/main.styl
+++ b/client/css/main.styl
@@ -1,4 +1,5 @@
@import colors
+@import mixins
/* latin */
@font-face
@@ -214,3 +215,8 @@ a .access-key
background: white
padding: 0 1em
z-index: 2
+
+/* hack to prevent text from being copied */
+[data-pseudo-content]:before {
+ content: attr(data-pseudo-content)
+}
diff --git a/client/css/mixins.styl b/client/css/mixins.styl
new file mode 100644
index 00000000..5daa0dc2
--- /dev/null
+++ b/client/css/mixins.styl
@@ -0,0 +1,6 @@
+unselectable()
+ -webkit-user-select: none
+ -moz-user-select: none
+ -ms-user-select: none
+ -o-user-select: none
+ user-select: none
diff --git a/client/html/post_readonly_sidebar.tpl b/client/html/post_readonly_sidebar.tpl
index af3bf3e8..61c701b4 100644
--- a/client/html/post_readonly_sidebar.tpl
+++ b/client/html/post_readonly_sidebar.tpl
@@ -76,11 +76,11 @@
--><% if (ctx.canListPosts) { %>'><% } %><%- tag %><%- tag %> <% if (ctx.canListPosts) { %><% } %><%- ctx.getTagUsages(tag) %><% } %>
diff --git a/client/js/controls/tag_input_control.js b/client/js/controls/tag_input_control.js
index 7abc5d6d..6622ce3c 100644
--- a/client/js/controls/tag_input_control.js
+++ b/client/js/controls/tag_input_control.js
@@ -296,7 +296,7 @@ class TagInputControl extends events.EventTarget {
}
searchLinkNode.setAttribute(
'href', '/posts/query=' + encodeURIComponent(tagName));
- searchLinkNode.textContent = tagName;
+ searchLinkNode.textContent = tagName + ' ';
searchLinkNode.addEventListener('click', e => {
e.preventDefault();
if (actualTag) {
@@ -307,17 +307,15 @@ class TagInputControl extends events.EventTarget {
}
});
- const usagesNode = views.htmlToDom(
- views.makeNonVoidElement(
- 'span',
- {class: 'append'},
- actualTag ? actualTag.usages : 0));
+ const usagesNode = document.createElement('span');
+ usagesNode.classList.add('append');
+ usagesNode.setAttribute(
+ 'data-pseudo-content', actualTag ? actualTag.usages : 0);
- const removalLinkNode = views.htmlToDom(
- views.makeNonVoidElement(
- 'a',
- {href: '#', class: 'append'},
- '×'));
+ const removalLinkNode = document.createElement('a');
+ removalLinkNode.classList.add('append');
+ removalLinkNode.setAttribute('href', '#');
+ removalLinkNode.setAttribute('data-pseudo-content', '×');
removalLinkNode.addEventListener('click', e => {
e.preventDefault();
this.deleteTag(tagName);
@@ -390,12 +388,12 @@ class TagInputControl extends events.EventTarget {
const weightNode = document.createElement('span');
weightNode.classList.add('tag-weight');
weightNode.classList.add('append');
- weightNode.textContent = weight;
+ weightNode.setAttribute('data-pseudo-content', weight);
const removeLinkNode = document.createElement('a');
removeLinkNode.classList.add('remove-tag');
removeLinkNode.classList.add('append');
- removeLinkNode.textContent = '×';
+ removeLinkNode.setAttribute('data-pseudo-content', '×');
removeLinkNode.setAttribute('href', '#');
removeLinkNode.addEventListener('click', e => {
e.preventDefault();