client/general: add empty href for link buttons
Ine464e69
I removed href='#' but I noticed that it broke some things. Readding href serves two purposes: - it makes links reachable with Tab key - it makes links clickable with Enter key The alternative to this approach was to introduce [tabindex] and [role] attributes. But not only using tabindex=0 with <a/> is questionable, it'd require adding a keyboard handler that'd intercept space and return key presses and simulated link clicks. Since it's best to leave this kind of thing to the native UI, I went with readding hrefs instead. I believe that hash hrefs, even though being a common practice, are silly, so I decided to settle down with empty hrefs. As a bonus, I added a snippet that prevents middle mouse clicks from opening such links/buttons in new tabs, which was the motivation fore464e69
.
This commit is contained in:
parent
44b2d9b830
commit
d5e197e6ea
18 changed files with 47 additions and 28 deletions
|
@ -32,13 +32,13 @@
|
|||
--><span class='score-container'></span><!--
|
||||
|
||||
--><% if (ctx.canEditComment) { %><!--
|
||||
--><a class='edit'><!--
|
||||
--><a href class='edit'><!--
|
||||
--><i class='fa fa-pencil'></i> edit<!--
|
||||
--></a><!--
|
||||
--><% } %><!--
|
||||
|
||||
--><% if (ctx.canDeleteComment) { %><!--
|
||||
--><a class='delete'><!--
|
||||
--><a href class='delete'><!--
|
||||
--><i class='fa fa-remove'></i> delete<!--
|
||||
--></a><!--
|
||||
--><% } %><!--
|
||||
|
|
|
@ -16,8 +16,8 @@
|
|||
|
||||
<nav class='buttons'>
|
||||
<ul>
|
||||
<li class='preview'><a>Preview</a></li>
|
||||
<li class='edit'><a>Edit</a></li>
|
||||
<li class='preview'><a href>Preview</a></li>
|
||||
<li class='edit'><a href>Edit</a></li>
|
||||
</ul>
|
||||
</nav>
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<section class='expander'>
|
||||
<header>
|
||||
<a>
|
||||
<a href>
|
||||
<%- ctx.title %>
|
||||
<i class='fa fa-chevron-down'></i>
|
||||
</a>
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
<% if (ctx.canFavorite) { %>
|
||||
<% if (ctx.ownFavorite) { %>
|
||||
<a class='remove-favorite'>
|
||||
<a href class='remove-favorite'>
|
||||
<i class='fa fa-heart'></i>
|
||||
<% } else { %>
|
||||
<a class='add-favorite'>
|
||||
<a href class='add-favorite'>
|
||||
<i class='fa fa-heart-o'></i>
|
||||
<% } %>
|
||||
<% } else { %>
|
||||
|
|
|
@ -57,9 +57,9 @@
|
|||
|
||||
<% if (ctx.canEditPostNotes) { %>
|
||||
<section class='notes'>
|
||||
<a class='add'>Add a note</a>
|
||||
<a href class='add'>Add a note</a>
|
||||
<%= ctx.makeTextarea({disabled: true, text: 'Content (supports Markdown)', rows: '8'}) %>
|
||||
<a class='delete inactive'>Delete selected note</a>
|
||||
<a href class='delete inactive'>Delete selected note</a>
|
||||
</section>
|
||||
<% } %>
|
||||
|
||||
|
@ -74,7 +74,7 @@
|
|||
<section class='post-thumbnail'>
|
||||
<label>Thumbnail</label>
|
||||
<div class='dropper-container'></div>
|
||||
<a>Discard custom thumbnail</a>
|
||||
<a href>Discard custom thumbnail</a>
|
||||
</section>
|
||||
<% } %>
|
||||
|
||||
|
@ -82,10 +82,10 @@
|
|||
<section class='management'>
|
||||
<ul>
|
||||
<% if (ctx.canFeaturePosts) { %>
|
||||
<li><a class='feature'>Feature this post on main page</a></li>
|
||||
<li><a href class='feature'>Feature this post on main page</a></li>
|
||||
<% } %>
|
||||
<% if (ctx.canDeletePosts) { %>
|
||||
<li><a class='delete'>Delete this post</a></li>
|
||||
<li><a href class='delete'>Delete this post</a></li>
|
||||
<% } %>
|
||||
</ul>
|
||||
</section>
|
||||
|
|
|
@ -26,10 +26,10 @@
|
|||
</section>
|
||||
|
||||
<section class='zoom'>
|
||||
<a class='fit-original'>Original zoom</a> ·
|
||||
<a class='fit-width'>fit width</a> ·
|
||||
<a class='fit-height'>height</a> ·
|
||||
<a class='fit-both'>both</a>
|
||||
<a href class='fit-original'>Original zoom</a> ·
|
||||
<a href class='fit-width'>fit width</a> ·
|
||||
<a href class='fit-height'>height</a> ·
|
||||
<a href class='fit-both'>both</a>
|
||||
</section>
|
||||
|
||||
<section class='search'>
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<li class='uploadable'>
|
||||
<a class='remove'>
|
||||
<a href class='remove'>
|
||||
<i class='fa fa-remove'></i>
|
||||
</a>
|
||||
|
||||
|
|
|
@ -12,11 +12,11 @@
|
|||
<% if (ctx.parameters.tag) { %>
|
||||
<span class='append'>Tagging with:</span>
|
||||
<% } else { %>
|
||||
<a class='mousetrap button append open-masstag'>Mass tag</a>
|
||||
<a href class='mousetrap button append open-masstag'>Mass tag</a>
|
||||
<% } %>
|
||||
<%= ctx.makeTextInput({name: 'masstag', value: ctx.parameters.tag}) %>
|
||||
<input class='mousetrap start-tagging' type='submit' value='Start tagging'/>
|
||||
<a class='mousetrap button append stop-tagging'>Stop tagging</a>
|
||||
<a href class='mousetrap button append stop-tagging'>Stop tagging</a>
|
||||
</form>
|
||||
<% } %>
|
||||
</div>
|
||||
|
|
|
@ -36,7 +36,7 @@
|
|||
<% } %>
|
||||
</a>
|
||||
<% if (ctx.parameters && ctx.parameters.tag) { %>
|
||||
<a data-post-id='<%= post.id %>' class='masstag'>
|
||||
<a href data-post-id='<%= post.id %>' class='masstag'>
|
||||
</a>
|
||||
<% } %>
|
||||
</li>
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<% if (ctx.canScore) { %>
|
||||
<a class='upvote'>
|
||||
<a href class='upvote'>
|
||||
<% if (ctx.ownScore == 1) { %>
|
||||
<i class='fa fa-thumbs-up'></i>
|
||||
<% } else { %>
|
||||
|
@ -9,13 +9,13 @@
|
|||
<span class='vim-nav-hint'>like</span>
|
||||
</a>
|
||||
<% } else { %>
|
||||
<a class='upvote inactive'>
|
||||
<a href class='upvote inactive'>
|
||||
<i class='fa fa-thumbs-o-up'></i>
|
||||
</a>
|
||||
<% } %>
|
||||
<span class='value'><%- ctx.score %></span>
|
||||
<% if (ctx.canScore) { %>
|
||||
<a class='downvote'>
|
||||
<a href class='downvote'>
|
||||
<% if (ctx.ownScore == -1) { %>
|
||||
<i class='fa fa-thumbs-down'></i>
|
||||
<% } else { %>
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
</table>
|
||||
|
||||
<% if (ctx.canCreate) { %>
|
||||
<p><a class='add'>Add new category</a></p>
|
||||
<p><a href class='add'>Add new category</a></p>
|
||||
<% } %>
|
||||
|
||||
<div class='messages'></div>
|
||||
|
|
|
@ -31,13 +31,13 @@
|
|||
<% if (ctx.tagCategory.tagCount) { %>
|
||||
<a class='inactive' title="Can't delete category in use">Remove</a>
|
||||
<% } else { %>
|
||||
<a>Remove</a>
|
||||
<a href>Remove</a>
|
||||
<% } %>
|
||||
</td>
|
||||
<% } %>
|
||||
<% if (ctx.canSetDefault) { %>
|
||||
<td class='set-default'>
|
||||
<a>Make default</a>
|
||||
<a href>Make default</a>
|
||||
</td>
|
||||
<% } %>
|
||||
</tr>
|
||||
|
|
|
@ -8,8 +8,8 @@
|
|||
<div class='wrapper'>
|
||||
<p>
|
||||
<span class='buttons'>
|
||||
<a class='opacity'><i class='fa fa-eye'></i></a>
|
||||
<a class='close'>×</a>
|
||||
<a href class='opacity'><i class='fa fa-eye'></i></a>
|
||||
<a href class='close'>×</a>
|
||||
</span>
|
||||
Suggested tags
|
||||
</p>
|
||||
|
|
|
@ -215,6 +215,7 @@ class AutoCompleteControl {
|
|||
const listItem = document.createElement('li');
|
||||
const link = document.createElement('a');
|
||||
link.innerHTML = resultItem.caption;
|
||||
link.setAtribute('href', '');
|
||||
link.setAttribute('data-key', resultItem.value);
|
||||
link.addEventListener(
|
||||
'mouseenter',
|
||||
|
|
|
@ -146,12 +146,14 @@ class PostEditSidebarControl extends events.EventTarget {
|
|||
}
|
||||
|
||||
_evtRemoveThumbnailClick(e) {
|
||||
e.preventDefault();
|
||||
this._thumbnailFileDropper.reset();
|
||||
this._newPostThumbnail = null;
|
||||
this._thumbnailRemovalLinkNode.style.display = 'none';
|
||||
}
|
||||
|
||||
_evtFeatureClick(e) {
|
||||
e.preventDefault();
|
||||
if (confirm('Are you sure you want to feature this post?')) {
|
||||
this.dispatchEvent(new CustomEvent('feature', {
|
||||
detail: {
|
||||
|
@ -162,6 +164,7 @@ class PostEditSidebarControl extends events.EventTarget {
|
|||
}
|
||||
|
||||
_evtDeleteClick(e) {
|
||||
e.preventDefault();
|
||||
if (confirm('Are you sure you want to delete this post?')) {
|
||||
this.dispatchEvent(new CustomEvent('delete', {
|
||||
detail: {
|
||||
|
@ -195,6 +198,7 @@ class PostEditSidebarControl extends events.EventTarget {
|
|||
}
|
||||
|
||||
_evtAddNoteClick(e) {
|
||||
e.preventDefault();
|
||||
if (e.target.classList.contains('inactive')) {
|
||||
return;
|
||||
}
|
||||
|
@ -203,6 +207,7 @@ class PostEditSidebarControl extends events.EventTarget {
|
|||
}
|
||||
|
||||
_evtDeleteNoteClick(e) {
|
||||
e.preventDefault();
|
||||
if (e.target.classList.contains('inactive')) {
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -251,6 +251,7 @@ class TagInputControl extends events.EventTarget {
|
|||
}
|
||||
|
||||
_evtAddTagButtonClick(e) {
|
||||
e.preventDefault();
|
||||
this.addTag(this._tagInputNode.value, SOURCE_USER_INPUT);
|
||||
this._tagInputNode.value = '';
|
||||
}
|
||||
|
@ -324,6 +325,7 @@ class TagInputControl extends events.EventTarget {
|
|||
|
||||
const removalLinkNode = document.createElement('a');
|
||||
removalLinkNode.classList.add('append');
|
||||
removalLinkNode.setAttribute('href', '')
|
||||
removalLinkNode.setAttribute('data-pseudo-content', '×');
|
||||
removalLinkNode.addEventListener('click', e => {
|
||||
e.preventDefault();
|
||||
|
@ -387,6 +389,7 @@ class TagInputControl extends events.EventTarget {
|
|||
const addLinkNode = document.createElement('a');
|
||||
addLinkNode.textContent = tagName;
|
||||
addLinkNode.classList.add('add-tag');
|
||||
addLinkNode.setAttribute('href', '');
|
||||
if (actualTag) {
|
||||
addLinkNode.classList.add(
|
||||
misc.makeCssName(actualTag.category, 'tag'));
|
||||
|
@ -405,6 +408,7 @@ class TagInputControl extends events.EventTarget {
|
|||
const removeLinkNode = document.createElement('a');
|
||||
removeLinkNode.classList.add('remove-tag');
|
||||
removeLinkNode.classList.add('append');
|
||||
removeLinkNode.setAttribute('href', '');
|
||||
removeLinkNode.setAttribute('data-pseudo-content', '×');
|
||||
removeLinkNode.addEventListener('click', e => {
|
||||
e.preventDefault();
|
||||
|
|
|
@ -476,6 +476,14 @@ document.addEventListener('input', e => {
|
|||
}
|
||||
});
|
||||
|
||||
// prevent opening buttons in new tabs
|
||||
document.addEventListener('click', e => {
|
||||
if (e.target.getAttribute('href') === '' && e.which === 2) {
|
||||
console.log('prevented');
|
||||
e.preventDefault();
|
||||
}
|
||||
});
|
||||
|
||||
module.exports = misc.arrayToObject([
|
||||
htmlToDom,
|
||||
getTemplate,
|
||||
|
|
|
@ -206,6 +206,7 @@ class PostUploadView extends events.EventTarget {
|
|||
}
|
||||
|
||||
_evtRemoveClick(e, uploadable) {
|
||||
e.preventDefault();
|
||||
this.removeUploadable(uploadable);
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue