BigW Consortium Gitlab
Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
G
gitlab-ce
Project
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
Registry
Registry
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Commits
Issue Boards
Open sidebar
Forest Godfrey
gitlab-ce
Commits
3b4c07ac
Commit
3b4c07ac
authored
Jun 16, 2017
by
Mike Greiling
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
refactor AwardsHandler into es class syntax
parent
442bd265
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
374 additions
and
379 deletions
+374
-379
awards_handler.js
app/assets/javascripts/awards_handler.js
+374
-379
No files found.
app/assets/javascripts/awards_handler.js
View file @
3b4c07ac
/* eslint-disable class-methods-use-this */
/* global Flash */
import
Cookies
from
'js-cookie'
;
...
...
@@ -68,141 +69,140 @@ function renderCategory(name, emojiList, opts = {}) {
`
;
}
function
AwardsHandler
()
{
this
.
eventListeners
=
[];
this
.
aliases
=
emojiAliases
;
// If the user shows intent let's pre-build the menu
this
.
registerEventListener
(
'one'
,
$
(
document
),
'mouseenter focus'
,
'.js-add-award'
,
'mouseenter focus'
,
()
=>
{
const
$menu
=
$
(
'.emoji-menu'
);
if
(
$menu
.
length
===
0
)
{
requestAnimationFrame
(()
=>
{
this
.
createEmojiMenu
();
});
}
// Prebuild the categoryMap
categoryMap
=
categoryMap
||
buildCategoryMap
();
});
this
.
registerEventListener
(
'on'
,
$
(
document
),
'click'
,
'.js-add-award'
,
(
e
)
=>
{
e
.
stopPropagation
();
e
.
preventDefault
();
this
.
showEmojiMenu
(
$
(
e
.
currentTarget
));
});
export
default
class
AwardsHandler
{
constructor
()
{
this
.
eventListeners
=
[];
this
.
aliases
=
emojiAliases
;
// If the user shows intent let's pre-build the menu
this
.
registerEventListener
(
'one'
,
$
(
document
),
'mouseenter focus'
,
'.js-add-award'
,
'mouseenter focus'
,
()
=>
{
const
$menu
=
$
(
'.emoji-menu'
);
if
(
$menu
.
length
===
0
)
{
requestAnimationFrame
(()
=>
{
this
.
createEmojiMenu
();
});
}
// Prebuild the categoryMap
categoryMap
=
categoryMap
||
buildCategoryMap
();
});
this
.
registerEventListener
(
'on'
,
$
(
document
),
'click'
,
'.js-add-award'
,
(
e
)
=>
{
e
.
stopPropagation
();
e
.
preventDefault
();
this
.
showEmojiMenu
(
$
(
e
.
currentTarget
));
});
this
.
registerEventListener
(
'on'
,
$
(
'html'
),
'click'
,
(
e
)
=>
{
const
$target
=
$
(
e
.
target
);
if
(
!
$target
.
closest
(
'.emoji-menu-content'
).
length
)
{
$
(
'.js-awards-block.current'
).
removeClass
(
'current'
);
}
if
(
!
$target
.
closest
(
'.emoji-menu'
).
length
)
{
if
(
$
(
'.emoji-menu'
).
is
(
':visible'
))
{
$
(
'.js-add-award.is-active'
).
removeClass
(
'is-active'
);
$
(
'.emoji-menu'
).
removeClass
(
'is-visible'
);
this
.
registerEventListener
(
'on'
,
$
(
'html'
),
'click'
,
(
e
)
=>
{
const
$target
=
$
(
e
.
target
);
if
(
!
$target
.
closest
(
'.emoji-menu-content'
).
length
)
{
$
(
'.js-awards-block.current'
).
removeClass
(
'current'
);
}
}
});
this
.
registerEventListener
(
'on'
,
$
(
document
),
'click'
,
'.js-emoji-btn'
,
(
e
)
=>
{
e
.
preventDefault
();
const
$target
=
$
(
e
.
currentTarget
);
const
$glEmojiElement
=
$target
.
find
(
'gl-emoji'
);
const
$spriteIconElement
=
$target
.
find
(
'.icon'
);
const
emoji
=
(
$glEmojiElement
.
length
?
$glEmojiElement
:
$spriteIconElement
).
data
(
'name'
);
$target
.
closest
(
'.js-awards-block'
).
addClass
(
'current'
);
this
.
addAward
(
this
.
getVotesBlock
(),
this
.
getAwardUrl
(),
emoji
);
});
}
if
(
!
$target
.
closest
(
'.emoji-menu'
).
length
)
{
if
(
$
(
'.emoji-menu'
).
is
(
':visible'
))
{
$
(
'.js-add-award.is-active'
).
removeClass
(
'is-active'
);
$
(
'.emoji-menu'
).
removeClass
(
'is-visible'
);
}
}
});
this
.
registerEventListener
(
'on'
,
$
(
document
),
'click'
,
'.js-emoji-btn'
,
(
e
)
=>
{
e
.
preventDefault
();
const
$target
=
$
(
e
.
currentTarget
);
const
$glEmojiElement
=
$target
.
find
(
'gl-emoji'
);
const
$spriteIconElement
=
$target
.
find
(
'.icon'
);
const
emoji
=
(
$glEmojiElement
.
length
?
$glEmojiElement
:
$spriteIconElement
).
data
(
'name'
);
$target
.
closest
(
'.js-awards-block'
).
addClass
(
'current'
);
this
.
addAward
(
this
.
getVotesBlock
(),
this
.
getAwardUrl
(),
emoji
);
});
}
AwardsHandler
.
prototype
.
registerEventListener
=
function
registerEventListener
(
method
=
'on'
,
element
,
...
args
)
{
element
[
method
].
call
(
element
,
...
args
);
this
.
eventListeners
.
push
({
element
,
args
,
});
};
registerEventListener
(
method
=
'on'
,
element
,
...
args
)
{
element
[
method
].
call
(
element
,
...
args
);
this
.
eventListeners
.
push
({
element
,
args
,
});
}
AwardsHandler
.
prototype
.
showEmojiMenu
=
function
showEmojiMenu
(
$addBtn
)
{
if
(
$addBtn
.
hasClass
(
'js-note-emoji'
))
{
$addBtn
.
closest
(
'.note'
).
find
(
'.js-awards-block'
).
addClass
(
'current'
);
}
else
{
$addBtn
.
closest
(
'.js-awards-block'
).
addClass
(
'current'
);
}
const
$menu
=
$
(
'.emoji-menu'
);
const
$thumbsBtn
=
$menu
.
find
(
'[data-name="thumbsup"], [data-name="thumbsdown"]'
).
parent
();
const
$userAuthored
=
this
.
isUserAuthored
(
$addBtn
);
if
(
$menu
.
length
)
{
if
(
$menu
.
is
(
'.is-visible'
))
{
$addBtn
.
removeClass
(
'is-active'
);
$menu
.
removeClass
(
'is-visible'
);
$
(
'.js-emoji-menu-search'
).
blur
();
showEmojiMenu
(
$addBtn
)
{
if
(
$addBtn
.
hasClass
(
'js-note-emoji'
))
{
$addBtn
.
closest
(
'.note'
).
find
(
'.js-awards-block'
).
addClass
(
'current'
);
}
else
{
$addBtn
.
addClass
(
'is-active'
);
this
.
positionMenu
(
$menu
,
$addBtn
);
$menu
.
addClass
(
'is-visible'
);
$
(
'.js-emoji-menu-search'
).
focus
();
$addBtn
.
closest
(
'.js-awards-block'
).
addClass
(
'current'
);
}
}
else
{
$addBtn
.
addClass
(
'is-loading is-active'
);
this
.
createEmojiMenu
(()
=>
{
const
$createdMenu
=
$
(
'.emoji-menu'
);
$addBtn
.
removeClass
(
'is-loading'
);
this
.
positionMenu
(
$createdMenu
,
$addBtn
);
return
setTimeout
(()
=>
{
$createdMenu
.
addClass
(
'is-visible'
);
const
$menu
=
$
(
'.emoji-menu'
);
const
$thumbsBtn
=
$menu
.
find
(
'[data-name="thumbsup"], [data-name="thumbsdown"]'
).
parent
();
const
$userAuthored
=
this
.
isUserAuthored
(
$addBtn
);
if
(
$menu
.
length
)
{
if
(
$menu
.
is
(
'.is-visible'
))
{
$addBtn
.
removeClass
(
'is-active'
);
$menu
.
removeClass
(
'is-visible'
);
$
(
'.js-emoji-menu-search'
).
blur
();
}
else
{
$addBtn
.
addClass
(
'is-active'
);
this
.
positionMenu
(
$menu
,
$addBtn
);
$menu
.
addClass
(
'is-visible'
);
$
(
'.js-emoji-menu-search'
).
focus
();
},
200
);
});
}
}
else
{
$addBtn
.
addClass
(
'is-loading is-active'
);
this
.
createEmojiMenu
(()
=>
{
const
$createdMenu
=
$
(
'.emoji-menu'
);
$addBtn
.
removeClass
(
'is-loading'
);
this
.
positionMenu
(
$createdMenu
,
$addBtn
);
return
setTimeout
(()
=>
{
$createdMenu
.
addClass
(
'is-visible'
);
$
(
'.js-emoji-menu-search'
).
focus
();
},
200
);
});
}
$thumbsBtn
.
toggleClass
(
'disabled'
,
$userAuthored
);
}
$thumbsBtn
.
toggleClass
(
'disabled'
,
$userAuthored
);
};
// Create the emoji menu with the first category of emojis.
// Then render the remaining categories of emojis one by one to avoid jank.
createEmojiMenu
(
callback
)
{
if
(
this
.
isCreatingEmojiMenu
)
{
return
;
}
this
.
isCreatingEmojiMenu
=
true
;
// Create the emoji menu with the first category of emojis.
// Then render the remaining categories of emojis one by one to avoid jank.
AwardsHandler
.
prototype
.
createEmojiMenu
=
function
createEmojiMenu
(
callback
)
{
if
(
this
.
isCreatingEmojiMenu
)
{
return
;
}
this
.
isCreatingEmojiMenu
=
true
;
// Render the first category
categoryMap
=
categoryMap
||
buildCategoryMap
();
const
categoryNameKey
=
Object
.
keys
(
categoryMap
)[
0
];
const
emojisInCategory
=
categoryMap
[
categoryNameKey
];
const
firstCategory
=
renderCategory
(
categoryLabelMap
[
categoryNameKey
],
emojisInCategory
);
// Render the frequently used
const
frequentlyUsedEmojis
=
this
.
getFrequentlyUsedEmojis
();
let
frequentlyUsedCatgegory
=
''
;
if
(
frequentlyUsedEmojis
.
length
>
0
)
{
frequentlyUsedCatgegory
=
renderCategory
(
'Frequently used'
,
frequentlyUsedEmojis
,
{
menuListClass
:
'frequent-emojis'
,
});
}
// Render the first category
categoryMap
=
categoryMap
||
buildCategoryMap
();
const
categoryNameKey
=
Object
.
keys
(
categoryMap
)[
0
];
const
emojisInCategory
=
categoryMap
[
categoryNameKey
];
const
firstCategory
=
renderCategory
(
categoryLabelMap
[
categoryNameKey
],
emojisInCategory
);
// Render the frequently used
const
frequentlyUsedEmojis
=
this
.
getFrequentlyUsedEmojis
();
let
frequentlyUsedCatgegory
=
''
;
if
(
frequentlyUsedEmojis
.
length
>
0
)
{
frequentlyUsedCatgegory
=
renderCategory
(
'Frequently used'
,
frequentlyUsedEmojis
,
{
menuListClass
:
'frequent-emojis'
,
});
}
const
emojiMenuMarkup
=
`
<div class="emoji-menu">
<input type="text" name="emoji-menu-search" value="" class="js-emoji-menu-search emoji-search search-input form-control" placeholder="Search emoji" />
const
emojiMenuMarkup
=
`
<div class="emoji-menu">
<input type="text" name="emoji-menu-search" value="" class="js-emoji-menu-search emoji-search search-input form-control" placeholder="Search emoji" />
<div class="emoji-menu-content">
${
frequentlyUsedCatgegory
}
${
firstCategory
}
<div class="emoji-menu-content">
${
frequentlyUsedCatgegory
}
${
firstCategory
}
</div>
</div>
</div>
`
;
`
;
document
.
body
.
insertAdjacentHTML
(
'beforeend'
,
emojiMenuMarkup
);
document
.
body
.
insertAdjacentHTML
(
'beforeend'
,
emojiMenuMarkup
);
this
.
addRemainingEmojiMenuCategories
();
this
.
setupSearch
();
if
(
callback
)
{
callback
();
this
.
addRemainingEmojiMenuCategories
();
this
.
setupSearch
();
if
(
callback
)
{
callback
();
}
}
};
AwardsHandler
.
prototype
.
addRemainingEmojiMenuCategories
=
function
addRemainingEmojiMenuCategories
()
{
addRemainingEmojiMenuCategories
()
{
if
(
this
.
isAddingRemainingEmojiMenuCategories
)
{
return
;
}
...
...
@@ -243,176 +243,174 @@ AwardsHandler
emojiContentElement
.
insertAdjacentHTML
(
'beforeend'
,
'<p>We encountered an error while adding the remaining categories</p>'
);
throw
new
Error
(
`Error occurred in addRemainingEmojiMenuCategories:
${
err
.
message
}
`
);
});
};
AwardsHandler
.
prototype
.
positionMenu
=
function
positionMenu
(
$menu
,
$addBtn
)
{
const
position
=
$addBtn
.
data
(
'position'
);
// The menu could potentially be off-screen or in a hidden overflow element
// So we position the element absolute in the body
const
css
=
{
top
:
`
${
$addBtn
.
offset
().
top
+
$addBtn
.
outerHeight
()}
px`
,
};
if
(
position
===
'right'
)
{
css
.
left
=
`
${(
$addBtn
.
offset
().
left
-
$menu
.
outerWidth
())
+
20
}
px`
;
$menu
.
addClass
(
'is-aligned-right'
);
}
else
{
css
.
left
=
`
${
$addBtn
.
offset
().
left
}
px`
;
$menu
.
removeClass
(
'is-aligned-right'
);
}
return
$menu
.
css
(
css
);
};
AwardsHandler
.
prototype
.
addAward
=
function
addAward
(
votesBlock
,
awardUrl
,
emoji
,
checkMutuality
,
callback
,
)
{
const
normalizedEmoji
=
this
.
normalizeEmojiName
(
emoji
);
const
$emojiButton
=
this
.
findEmojiIcon
(
votesBlock
,
normalizedEmoji
).
parent
();
this
.
postEmoji
(
$emojiButton
,
awardUrl
,
normalizedEmoji
,
()
=>
{
this
.
addAwardToEmojiBar
(
votesBlock
,
normalizedEmoji
,
checkMutuality
);
return
typeof
callback
===
'function'
?
callback
()
:
undefined
;
});
$
(
'.emoji-menu'
).
removeClass
(
'is-visible'
);
$
(
'.js-add-award.is-active'
).
removeClass
(
'is-active'
);
};
}
AwardsHandler
.
prototype
.
addAwardToEmojiBar
=
function
addAwardToEmojiBar
(
votesBlock
,
emoji
,
checkForMutuality
,
)
{
if
(
checkForMutuality
||
checkForMutuality
===
null
)
{
this
.
checkMutuality
(
votesBlock
,
emoji
);
}
this
.
addEmojiToFrequentlyUsedList
(
emoji
);
const
normalizedEmoji
=
this
.
normalizeEmojiName
(
emoji
);
const
$emojiButton
=
this
.
findEmojiIcon
(
votesBlock
,
normalizedEmoji
).
parent
();
if
(
$emojiButton
.
length
>
0
)
{
if
(
this
.
isActive
(
$emojiButton
))
{
this
.
decrementCounter
(
$emojiButton
,
normalizedEmoji
);
positionMenu
(
$menu
,
$addBtn
)
{
const
position
=
$addBtn
.
data
(
'position'
);
// The menu could potentially be off-screen or in a hidden overflow element
// So we position the element absolute in the body
const
css
=
{
top
:
`
${
$addBtn
.
offset
().
top
+
$addBtn
.
outerHeight
()}
px`
,
};
if
(
position
===
'right'
)
{
css
.
left
=
`
${(
$addBtn
.
offset
().
left
-
$menu
.
outerWidth
())
+
20
}
px`
;
$menu
.
addClass
(
'is-aligned-right'
);
}
else
{
const
counter
=
$emojiButton
.
find
(
'.js-counter'
);
counter
.
text
(
parseInt
(
counter
.
text
(),
10
)
+
1
);
$emojiButton
.
addClass
(
'active'
);
this
.
addYouToUserList
(
votesBlock
,
normalizedEmoji
);
this
.
animateEmoji
(
$emojiButton
);
css
.
left
=
`
${
$addBtn
.
offset
().
left
}
px`
;
$menu
.
removeClass
(
'is-aligned-right'
);
}
}
else
{
votesBlock
.
removeClass
(
'hidden'
);
this
.
createEmoji
(
votesBlock
,
normalizedEmoji
);
return
$menu
.
css
(
css
);
}
};
AwardsHandler
.
prototype
.
getVotesBlock
=
function
getVotesBlock
()
{
const
currentBlock
=
$
(
'.js-awards-block.current'
);
let
resultantVotesBlock
=
currentBlock
;
if
(
currentBlock
.
length
===
0
)
{
resultantVotesBlock
=
$
(
'.js-awards-block'
).
eq
(
0
);
addAward
(
votesBlock
,
awardUrl
,
emoji
,
checkMutuality
,
callback
,
)
{
const
normalizedEmoji
=
this
.
normalizeEmojiName
(
emoji
);
const
$emojiButton
=
this
.
findEmojiIcon
(
votesBlock
,
normalizedEmoji
).
parent
();
this
.
postEmoji
(
$emojiButton
,
awardUrl
,
normalizedEmoji
,
()
=>
{
this
.
addAwardToEmojiBar
(
votesBlock
,
normalizedEmoji
,
checkMutuality
);
return
typeof
callback
===
'function'
?
callback
()
:
undefined
;
});
$
(
'.emoji-menu'
).
removeClass
(
'is-visible'
);
$
(
'.js-add-award.is-active'
).
removeClass
(
'is-active'
);
}
return
resultantVotesBlock
;
};
addAwardToEmojiBar
(
votesBlock
,
emoji
,
checkForMutuality
,
)
{
if
(
checkForMutuality
||
checkForMutuality
===
null
)
{
this
.
checkMutuality
(
votesBlock
,
emoji
);
}
this
.
addEmojiToFrequentlyUsedList
(
emoji
);
const
normalizedEmoji
=
this
.
normalizeEmojiName
(
emoji
);
const
$emojiButton
=
this
.
findEmojiIcon
(
votesBlock
,
normalizedEmoji
).
parent
();
if
(
$emojiButton
.
length
>
0
)
{
if
(
this
.
isActive
(
$emojiButton
))
{
this
.
decrementCounter
(
$emojiButton
,
normalizedEmoji
);
}
else
{
const
counter
=
$emojiButton
.
find
(
'.js-counter'
);
counter
.
text
(
parseInt
(
counter
.
text
(),
10
)
+
1
);
$emojiButton
.
addClass
(
'active'
);
this
.
addYouToUserList
(
votesBlock
,
normalizedEmoji
);
this
.
animateEmoji
(
$emojiButton
);
}
}
else
{
votesBlock
.
removeClass
(
'hidden'
);
this
.
createEmoji
(
votesBlock
,
normalizedEmoji
);
}
}
AwardsHandler
.
prototype
.
getAwardUrl
=
function
getAwardUrl
()
{
return
this
.
getVotesBlock
().
data
(
'award-url'
);
};
getVotesBlock
()
{
const
currentBlock
=
$
(
'.js-awards-block.current'
);
let
resultantVotesBlock
=
currentBlock
;
if
(
currentBlock
.
length
===
0
)
{
resultantVotesBlock
=
$
(
'.js-awards-block'
).
eq
(
0
);
}
return
resultantVotesBlock
;
}
AwardsHandler
.
prototype
.
checkMutuality
=
function
checkMutuality
(
votesBlock
,
emoji
)
{
const
awardUrl
=
this
.
getAwardUrl
();
if
(
emoji
===
'thumbsup'
||
emoji
===
'thumbsdown'
)
{
const
mutualVote
=
emoji
===
'thumbsup'
?
'thumbsdown'
:
'thumbsup'
;
const
$emojiButton
=
votesBlock
.
find
(
`[data-name="
${
mutualVote
}
"]`
).
parent
();
const
isAlreadyVoted
=
$emojiButton
.
hasClass
(
'active'
);
if
(
isAlreadyVoted
)
{
this
.
addAward
(
votesBlock
,
awardUrl
,
mutualVote
,
false
);
getAwardUrl
()
{
return
this
.
getVotesBlock
().
data
(
'award-url'
);
}
checkMutuality
(
votesBlock
,
emoji
)
{
const
awardUrl
=
this
.
getAwardUrl
();
if
(
emoji
===
'thumbsup'
||
emoji
===
'thumbsdown'
)
{
const
mutualVote
=
emoji
===
'thumbsup'
?
'thumbsdown'
:
'thumbsup'
;
const
$emojiButton
=
votesBlock
.
find
(
`[data-name="
${
mutualVote
}
"]`
).
parent
();
const
isAlreadyVoted
=
$emojiButton
.
hasClass
(
'active'
);
if
(
isAlreadyVoted
)
{
this
.
addAward
(
votesBlock
,
awardUrl
,
mutualVote
,
false
);
}
}
}
};
AwardsHandler
.
prototype
.
isActive
=
function
isActive
(
$emojiButton
)
{
return
$emojiButton
.
hasClass
(
'active'
);
};
isActive
(
$emojiButton
)
{
return
$emojiButton
.
hasClass
(
'active'
);
}
AwardsHandler
.
prototype
.
isUserAuthored
=
function
isUserAuthored
(
$button
)
{
return
$button
.
hasClass
(
'js-user-authored'
);
};
isUserAuthored
(
$button
)
{
return
$button
.
hasClass
(
'js-user-authored'
);
}
AwardsHandler
.
prototype
.
decrementCounter
=
function
decrementCounter
(
$emojiButton
,
emoji
)
{
const
counter
=
$
(
'.js-counter'
,
$emojiButton
);
const
counterNumber
=
parseInt
(
counter
.
text
(),
10
);
if
(
counterNumber
>
1
)
{
counter
.
text
(
counterNumber
-
1
);
this
.
removeYouFromUserList
(
$emojiButton
);
}
else
if
(
emoji
===
'thumbsup'
||
emoji
===
'thumbsdown'
)
{
$emojiButton
.
tooltip
(
'destroy'
);
counter
.
text
(
'0'
);
this
.
removeYouFromUserList
(
$emojiButton
);
if
(
$emojiButton
.
parents
(
'.note'
).
length
)
{
decrementCounter
(
$emojiButton
,
emoji
)
{
const
counter
=
$
(
'.js-counter'
,
$emojiButton
);
const
counterNumber
=
parseInt
(
counter
.
text
(),
10
);
if
(
counterNumber
>
1
)
{
counter
.
text
(
counterNumber
-
1
);
this
.
removeYouFromUserList
(
$emojiButton
);
}
else
if
(
emoji
===
'thumbsup'
||
emoji
===
'thumbsdown'
)
{
$emojiButton
.
tooltip
(
'destroy'
);
counter
.
text
(
'0'
);
this
.
removeYouFromUserList
(
$emojiButton
);
if
(
$emojiButton
.
parents
(
'.note'
).
length
)
{
this
.
removeEmoji
(
$emojiButton
);
}
}
else
{
this
.
removeEmoji
(
$emojiButton
);
}
}
else
{
this
.
removeEmoji
(
$emojiButton
);
return
$emojiButton
.
removeClass
(
'active'
);
}
return
$emojiButton
.
removeClass
(
'active'
);
};
AwardsHandler
.
prototype
.
removeEmoji
=
function
removeEmoji
(
$emojiButton
)
{
$emojiButton
.
tooltip
(
'destroy'
);
$emojiButton
.
remove
();
const
$votesBlock
=
this
.
getVotesBlock
();
if
(
$votesBlock
.
find
(
'.js-emoji-btn'
).
length
===
0
)
{
$votesBlock
.
addClass
(
'hidden'
);
removeEmoji
(
$emojiButton
)
{
$emojiButton
.
tooltip
(
'destroy'
);
$emojiButton
.
remove
();
const
$votesBlock
=
this
.
getVotesBlock
();
if
(
$votesBlock
.
find
(
'.js-emoji-btn'
).
length
===
0
)
{
$votesBlock
.
addClass
(
'hidden'
);
}
}
};
AwardsHandler
.
prototype
.
getAwardTooltip
=
function
getAwardTooltip
(
$awardBlock
)
{
return
$awardBlock
.
attr
(
'data-original-title'
)
||
$awardBlock
.
attr
(
'data-title'
)
||
''
;
};
AwardsHandler
.
prototype
.
toSentence
=
function
toSentence
(
list
)
{
let
sentence
;
if
(
list
.
length
<=
2
)
{
sentence
=
list
.
join
(
' and '
);
}
else
{
sentence
=
`
${
list
.
slice
(
0
,
-
1
).
join
(
', '
)}
, and
${
list
[
list
.
length
-
1
]}
`
;
getAwardTooltip
(
$awardBlock
)
{
return
$awardBlock
.
attr
(
'data-original-title'
)
||
$awardBlock
.
attr
(
'data-title'
)
||
''
;
}
return
sentence
;
};
toSentence
(
list
)
{
let
sentence
;
if
(
list
.
length
<=
2
)
{
sentence
=
list
.
join
(
' and '
);
}
else
{
sentence
=
`
${
list
.
slice
(
0
,
-
1
).
join
(
', '
)}
, and
${
list
[
list
.
length
-
1
]}
`
;
}
AwardsHandler
.
prototype
.
removeYouFromUserList
=
function
removeYouFromUserList
(
$emojiButton
)
{
const
awardBlock
=
$emojiButton
;
const
originalTitle
=
this
.
getAwardTooltip
(
awardBlock
);
const
authors
=
originalTitle
.
split
(
FROM_SENTENCE_REGEX
);
authors
.
splice
(
authors
.
indexOf
(
'You'
),
1
);
return
awardBlock
.
closest
(
'.js-emoji-btn'
)
.
removeData
(
'title'
)
.
removeAttr
(
'data-title'
)
.
removeAttr
(
'data-original-title'
)
.
attr
(
'title'
,
this
.
toSentence
(
authors
))
.
tooltip
(
'fixTitle'
);
};
return
sentence
;
}
AwardsHandler
.
prototype
.
addYouToUserList
=
function
addYouToUserList
(
votesBlock
,
emoji
)
{
const
awardBlock
=
this
.
findEmojiIcon
(
votesBlock
,
emoji
).
parent
();
const
origTitle
=
this
.
getAwardTooltip
(
awardBlock
);
let
users
=
[];
if
(
origTitle
)
{
users
=
origTitle
.
trim
().
split
(
FROM_SENTENCE_REGEX
);
}
users
.
unshift
(
'You'
);
return
awardBlock
.
attr
(
'title'
,
this
.
toSentence
(
users
))
.
tooltip
(
'fixTitle'
);
};
removeYouFromUserList
(
$emojiButton
)
{
const
awardBlock
=
$emojiButton
;
const
originalTitle
=
this
.
getAwardTooltip
(
awardBlock
);
const
authors
=
originalTitle
.
split
(
FROM_SENTENCE_REGEX
);
authors
.
splice
(
authors
.
indexOf
(
'You'
),
1
);
return
awardBlock
.
closest
(
'.js-emoji-btn'
)
.
removeData
(
'title'
)
.
removeAttr
(
'data-title'
)
.
removeAttr
(
'data-original-title'
)
.
attr
(
'title'
,
this
.
toSentence
(
authors
))
.
tooltip
(
'fixTitle'
);
}
addYouToUserList
(
votesBlock
,
emoji
)
{
const
awardBlock
=
this
.
findEmojiIcon
(
votesBlock
,
emoji
).
parent
();
const
origTitle
=
this
.
getAwardTooltip
(
awardBlock
);
let
users
=
[];
if
(
origTitle
)
{
users
=
origTitle
.
trim
().
split
(
FROM_SENTENCE_REGEX
);
}
users
.
unshift
(
'You'
);
return
awardBlock
.
attr
(
'title'
,
this
.
toSentence
(
users
))
.
tooltip
(
'fixTitle'
);
}
AwardsHandler
.
prototype
.
createAwardButtonForVotesBlock
=
function
createAwardButtonForVotesBlock
(
votesBlock
,
emojiName
)
{
createAwardButtonForVotesBlock
(
votesBlock
,
emojiName
)
{
const
buttonHtml
=
`
<button class="btn award-control js-emoji-btn has-tooltip active" title="You" data-placement="bottom">
${
glEmojiTag
(
emojiName
)}
...
...
@@ -424,144 +422,141 @@ AwardsHandler
this
.
animateEmoji
(
$emojiButton
);
$
(
'.award-control'
).
tooltip
();
votesBlock
.
removeClass
(
'current'
);
}
;
}
AwardsHandler
.
prototype
.
animateEmoji
=
function
animateEmoji
(
$emoji
)
{
const
className
=
'pulse animated once short'
;
$emoji
.
addClass
(
className
);
animateEmoji
(
$emoji
)
{
const
className
=
'pulse animated once short'
;
$emoji
.
addClass
(
className
);
this
.
registerEventListener
(
'on'
,
$emoji
,
animationEndEventString
,
(
e
)
=>
{
$
(
e
.
currentTarget
).
removeClass
(
className
);
});
};
this
.
registerEventListener
(
'on'
,
$emoji
,
animationEndEventString
,
(
e
)
=>
{
$
(
e
.
currentTarget
).
removeClass
(
className
);
});
}
AwardsHandler
.
prototype
.
createEmoji
=
function
createEmoji
(
votesBlock
,
emoji
)
{
if
(
$
(
'.emoji-menu'
).
length
)
{
this
.
createAwardButtonForVotesBlock
(
votesBlock
,
emoji
);
createEmoji
(
votesBlock
,
emoji
)
{
if
(
$
(
'.emoji-menu'
).
length
)
{
this
.
createAwardButtonForVotesBlock
(
votesBlock
,
emoji
);
}
this
.
createEmojiMenu
(()
=>
{
this
.
createAwardButtonForVotesBlock
(
votesBlock
,
emoji
);
});
}
this
.
createEmojiMenu
(()
=>
{
this
.
createAwardButtonForVotesBlock
(
votesBlock
,
emoji
);
});
};
AwardsHandler
.
prototype
.
postEmoji
=
function
postEmoji
(
$emojiButton
,
awardUrl
,
emoji
,
callback
)
{
if
(
this
.
isUserAuthored
(
$emojiButton
))
{
this
.
userAuthored
(
$emojiButton
);
}
else
{
$
.
post
(
awardUrl
,
{
name
:
emoji
,
},
(
data
)
=>
{
if
(
data
.
ok
)
{
callback
();
}
}).
fail
(()
=>
new
Flash
(
'Something went wrong on our end.'
));
postEmoji
(
$emojiButton
,
awardUrl
,
emoji
,
callback
)
{
if
(
this
.
isUserAuthored
(
$emojiButton
))
{
this
.
userAuthored
(
$emojiButton
);
}
else
{
$
.
post
(
awardUrl
,
{
name
:
emoji
,
},
(
data
)
=>
{
if
(
data
.
ok
)
{
callback
();
}
}).
fail
(()
=>
new
Flash
(
'Something went wrong on our end.'
));
}
}
};
AwardsHandler
.
prototype
.
findEmojiIcon
=
function
findEmojiIcon
(
votesBlock
,
emoji
)
{
return
votesBlock
.
find
(
`.js-emoji-btn [data-name="
${
emoji
}
"]`
);
};
findEmojiIcon
(
votesBlock
,
emoji
)
{
return
votesBlock
.
find
(
`.js-emoji-btn [data-name="
${
emoji
}
"]`
);
}
AwardsHandler
.
prototype
.
userAuthored
=
function
userAuthored
(
$emojiButton
)
{
const
oldTitle
=
this
.
getAwardTooltip
(
$emojiButton
);
const
newTitle
=
'You cannot vote on your own issue, MR and note'
;
gl
.
utils
.
updateTooltipTitle
(
$emojiButton
,
newTitle
).
tooltip
(
'show'
);
// Restore tooltip back to award list
return
setTimeout
(()
=>
{
$emojiButton
.
tooltip
(
'hide'
);
gl
.
utils
.
updateTooltipTitle
(
$emojiButton
,
oldTitle
);
},
2800
);
};
userAuthored
(
$emojiButton
)
{
const
oldTitle
=
this
.
getAwardTooltip
(
$emojiButton
);
const
newTitle
=
'You cannot vote on your own issue, MR and note'
;
gl
.
utils
.
updateTooltipTitle
(
$emojiButton
,
newTitle
).
tooltip
(
'show'
);
// Restore tooltip back to award list
return
setTimeout
(()
=>
{
$emojiButton
.
tooltip
(
'hide'
);
gl
.
utils
.
updateTooltipTitle
(
$emojiButton
,
oldTitle
);
},
2800
);
}
AwardsHandler
.
prototype
.
scrollToAwards
=
function
scrollToAwards
()
{
const
options
=
{
scrollTop
:
$
(
'.awards'
).
offset
().
top
-
110
,
};
return
$
(
'body, html'
).
animate
(
options
,
200
);
};
scrollToAwards
()
{
const
options
=
{
scrollTop
:
$
(
'.awards'
).
offset
().
top
-
110
,
};
return
$
(
'body, html'
).
animate
(
options
,
200
);
}
AwardsHandler
.
prototype
.
normalizeEmojiName
=
function
normalizeEmojiName
(
emoji
)
{
return
Object
.
prototype
.
hasOwnProperty
.
call
(
this
.
aliases
,
emoji
)
?
this
.
aliases
[
emoji
]
:
emoji
;
};
normalizeEmojiName
(
emoji
)
{
return
Object
.
prototype
.
hasOwnProperty
.
call
(
this
.
aliases
,
emoji
)
?
this
.
aliases
[
emoji
]
:
emoji
;
}
AwardsHandler
.
prototype
.
addEmojiToFrequentlyUsedList
=
function
addEmojiToFrequentlyUsedList
(
emoji
)
{
addEmojiToFrequentlyUsedList
(
emoji
)
{
if
(
isEmojiNameValid
(
emoji
))
{
this
.
frequentlyUsedEmojis
=
_
.
uniq
(
this
.
getFrequentlyUsedEmojis
().
concat
(
emoji
));
Cookies
.
set
(
'frequently_used_emojis'
,
this
.
frequentlyUsedEmojis
.
join
(
','
),
{
expires
:
365
});
}
};
AwardsHandler
.
prototype
.
getFrequentlyUsedEmojis
=
function
getFrequentlyUsedEmojis
()
{
return
this
.
frequentlyUsedEmojis
||
(()
=>
{
const
frequentlyUsedEmojis
=
_
.
uniq
((
Cookies
.
get
(
'frequently_used_emojis'
)
||
''
).
split
(
','
));
this
.
frequentlyUsedEmojis
=
frequentlyUsedEmojis
.
filter
(
inputName
=>
isEmojiNameValid
(
inputName
),
);
}
return
this
.
frequentlyUsedEmojis
;
})();
};
getFrequentlyUsedEmojis
()
{
return
this
.
frequentlyUsedEmojis
||
(()
=>
{
const
frequentlyUsedEmojis
=
_
.
uniq
((
Cookies
.
get
(
'frequently_used_emojis'
)
||
''
).
split
(
','
));
this
.
frequentlyUsedEmojis
=
frequentlyUsedEmojis
.
filter
(
inputName
=>
isEmojiNameValid
(
inputName
),
);
AwardsHandler
.
prototype
.
setupSearch
=
function
setupSearch
()
{
const
$search
=
$
(
'.js-emoji-menu-search'
);
return
this
.
frequentlyUsedEmojis
;
})();
}
this
.
registerEventListener
(
'on'
,
$search
,
'input'
,
(
e
)
=>
{
const
term
=
$
(
e
.
target
).
val
().
trim
();
this
.
searchEmojis
(
term
);
});
setupSearch
()
{
const
$search
=
$
(
'.js-emoji-menu-search'
);
const
$menu
=
$
(
'.emoji-menu'
);
this
.
registerEventListener
(
'on'
,
$menu
,
transitionEndEventString
,
(
e
)
=>
{
if
(
e
.
target
===
e
.
currentTarget
)
{
// Clear the search
this
.
searchEmojis
(
''
);
}
});
};
this
.
registerEventListener
(
'on'
,
$search
,
'input'
,
(
e
)
=>
{
const
term
=
$
(
e
.
target
).
val
().
trim
();
this
.
searchEmojis
(
term
);
});
AwardsHandler
.
prototype
.
searchEmojis
=
function
searchEmojis
(
term
)
{
const
$search
=
$
(
'.js-emoji-menu-search'
);
$search
.
val
(
term
);
// Clean previous search results
$
(
'ul.emoji-menu-search, h5.emoji-search-title'
).
remove
();
if
(
term
.
length
>
0
)
{
// Generate a search result block
const
h5
=
$
(
'<h5 class="emoji-search-title"/>'
).
text
(
'Search results'
);
const
foundEmojis
=
this
.
findMatchingEmojiElements
(
term
).
show
();
const
ul
=
$
(
'<ul>'
).
addClass
(
'emoji-menu-list emoji-menu-search'
).
append
(
foundEmojis
);
$
(
'.emoji-menu-content ul, .emoji-menu-content h5'
).
hide
();
$
(
'.emoji-menu-content'
).
append
(
h5
).
append
(
ul
);
}
else
{
$
(
'.emoji-menu-content'
).
children
().
show
();
const
$menu
=
$
(
'.emoji-menu'
);
this
.
registerEventListener
(
'on'
,
$menu
,
transitionEndEventString
,
(
e
)
=>
{
if
(
e
.
target
===
e
.
currentTarget
)
{
// Clear the search
this
.
searchEmojis
(
''
);
}
});
}
};
AwardsHandler
.
prototype
.
findMatchingEmojiElements
=
function
findMatchingEmojiElements
(
term
)
{
const
safeTerm
=
term
.
toLowerCase
();
const
namesMatchingAlias
=
[];
Object
.
keys
(
emojiAliases
).
forEach
((
alias
)
=>
{
if
(
alias
.
indexOf
(
safeTerm
)
>=
0
)
{
namesMatchingAlias
.
push
(
emojiAliases
[
alias
]);
searchEmojis
(
term
)
{
const
$search
=
$
(
'.js-emoji-menu-search'
);
$search
.
val
(
term
);
// Clean previous search results
$
(
'ul.emoji-menu-search, h5.emoji-search-title'
).
remove
();
if
(
term
.
length
>
0
)
{
// Generate a search result block
const
h5
=
$
(
'<h5 class="emoji-search-title"/>'
).
text
(
'Search results'
);
const
foundEmojis
=
this
.
findMatchingEmojiElements
(
term
).
show
();
const
ul
=
$
(
'<ul>'
).
addClass
(
'emoji-menu-list emoji-menu-search'
).
append
(
foundEmojis
);
$
(
'.emoji-menu-content ul, .emoji-menu-content h5'
).
hide
();
$
(
'.emoji-menu-content'
).
append
(
h5
).
append
(
ul
);
}
else
{
$
(
'.emoji-menu-content'
).
children
().
show
();
}
});
const
$matchingElements
=
namesMatchingAlias
.
concat
(
safeTerm
)
.
reduce
(
(
$result
,
searchTerm
)
=>
$result
.
add
(
$
(
`.emoji-menu-list:not(.frequent-emojis) [data-name*="
${
searchTerm
}
"]`
)),
$
([]),
);
return
$matchingElements
.
closest
(
'li'
).
clone
();
};
}
AwardsHandler
.
prototype
.
destroy
=
function
destroy
()
{
this
.
eventListeners
.
forEach
((
entry
)
=>
{
entry
.
element
.
off
.
call
(
entry
.
element
,
...
entry
.
args
);
});
$
(
'.emoji-menu'
).
remove
();
};
findMatchingEmojiElements
(
term
)
{
const
safeTerm
=
term
.
toLowerCase
();
const
namesMatchingAlias
=
[];
Object
.
keys
(
emojiAliases
).
forEach
((
alias
)
=>
{
if
(
alias
.
indexOf
(
safeTerm
)
>=
0
)
{
namesMatchingAlias
.
push
(
emojiAliases
[
alias
]);
}
});
const
$matchingElements
=
namesMatchingAlias
.
concat
(
safeTerm
)
.
reduce
(
(
$result
,
searchTerm
)
=>
$result
.
add
(
$
(
`.emoji-menu-list:not(.frequent-emojis) [data-name*="
${
searchTerm
}
"]`
)),
$
([]),
);
return
$matchingElements
.
closest
(
'li'
).
clone
();
}
export
default
AwardsHandler
;
destroy
()
{
this
.
eventListeners
.
forEach
((
entry
)
=>
{
entry
.
element
.
off
.
call
(
entry
.
element
,
...
entry
.
args
);
});
$
(
'.emoji-menu'
).
remove
();
}
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment