</div>
<div class="contentItemMetaIcons">
- {if MODULE_LIKE && $__wcf->getSession()->getPermission('user.like.canViewLike') && ($article->likes || $article->dislikes || $article->neutralReactions)}
- <div class="contentItemMetaIcon reputationCounter {if $article->cumulativeLikes > 0}positive{elseif $article->cumulativeLikes < 0}negative{else}neutral{/if}">
- <span aria-label="{lang cumulativeLikes=$article->cumulativeLikes}wcf.like.reputation.label{/lang}">
- {if $article->cumulativeLikes > 0}+{elseif $article->cumulativeLikes == 0}±{/if}{#$article->cumulativeLikes}
- </span>
- </div>
- {/if}
<div class="contentItemMetaIcon">
<span class="icon icon16 fa-comments"></span>
<span aria-label="{$article->getDiscussionProvider()->getDiscussionCountPhrase()}">
{if $__wcf->session->getPermission('user.like.canViewLike')}
- <ul class="reactionSummaryList{if $isTiny|isset && $isTiny} reactionSummaryListTiny{/if} jsOnly" data-object-type="{$objectType}" data-object-id="{$objectID}">
- {if $reactionData[$objectID]|isset && $reactionData[$objectID]->getReactions()|is_array}
- {foreach from=$reactionData[$objectID]->getReactions() key=reactionTypeID item=reaction}
- <li class="reactCountButton jsTooltip" data-reaction-type-id="{$reactionTypeID}" title="{lang}wcf.reactions.summary.listReactions{/lang}"><span class="reactionCount">{$reaction[reactionCount]|shortUnit}</span> {@$reaction[renderedReactionIcon]}</li>
+ {assign var='_reactionSummaryListReactions' value=null}
+ {if $reactionData[$objectID]|isset}
+ {assign var='_reactionSummaryListReactions' value=$reactionData[$objectID]->getReactions()}
+ {/if}
+ <a href="#" class="reactionSummaryList{if $isTiny|isset && $isTiny} reactionSummaryListTiny{/if} jsOnly jsTooltip" data-object-type="{$objectType}" data-object-id="{$objectID}" title="{lang}wcf.reactions.summary.listReactions{/lang}"{if $_reactionSummaryListReactions|empty} style="display: none;"{/if}>
+ {if !$_reactionSummaryListReactions|empty}
+ {foreach from=$_reactionSummaryListReactions key=reactionTypeID item=reaction}
+ <span class="reactCountButton" data-reaction-type-id="{@$reactionTypeID}">
+ {@$reaction[renderedReactionIcon]}
+ <span class="reactionCount">{$reaction[reactionCount]|shortUnit}</span>
+ </span>
{/foreach}
{/if}
- </ul>
-{/if}
\ No newline at end of file
+ </a>
+{/if}
src="{@$__wcf->getPath()}images/reaction/{$reactionType->iconFile}"
class="reactionType"
data-reaction-type-id="{$reactionType->reactionTypeID}"
-/>
+>
style="width:24px;height:24px"
class="reactionType"
data-reaction-type-id="{$reactionType->reactionTypeID}"
-/>
+>
continue;
}
+ objectId = ~~elData(element, 'object-id');
elementData = {
reactButton: null,
summary: null,
- objectId: ~~elData(element, 'object-id'),
+ objectId: objectId,
element: element
};
this._containers.set(DomUtil.identify(element), elementData);
this._initReactionCountButtons(element, elementData);
-
- if (!this._objects.has(~~elData(element, 'object-id'))) {
- var objects = [];
- }
- else {
- var objects = this._objects.get(~~elData(element, 'object-id'));
+
+ var objects = [];
+ if (this._objects.has(objectId)) {
+ objects = this._objects.get(objectId);
}
objects.push(elementData);
- this._objects.set(~~elData(element, 'object-id'), objects);
+ this._objects.set(objectId, objects);
triggerChange = true;
}
// summary list for the object not found; abort
if (summaryList === null) return;
- var sortedElements = {}, elements = elBySelAll('li', summaryList);
+ var sortedElements = {}, elements = elBySelAll('.reactCountButton', summaryList);
for (var i = 0, length = elements.length; i < length; i++) {
- if (data[elData(elements[i], 'reaction-type-id')] !== undefined) {
- sortedElements[elData(elements[i], 'reaction-type-id')] = elements[i];
+ var reactionTypeId = elData(elements[i], 'reaction-type-id');
+ if (data.hasOwnProperty(reactionTypeId)) {
+ sortedElements[reactionTypeId] = elements[i];
}
else {
- // reaction has no longer reactions
+ // The reaction no longer has any reactions.
elRemove(elements[i]);
}
}
reactionCount.innerHTML = StringUtil.shortUnit(data[key]);
}
else if (REACTION_TYPES[key] !== undefined) {
- // create element
- var createdElement = elCreate('li');
+ var createdElement = elCreate('span');
createdElement.className = 'reactCountButton';
+ createdElement.innerHTML = REACTION_TYPES[key].renderedIcon;
elData(createdElement, 'reaction-type-id', key);
-
+
var countSpan = elCreate('span');
countSpan.className = 'reactionCount';
countSpan.innerHTML = StringUtil.shortUnit(data[key]);
createdElement.appendChild(countSpan);
- createdElement.innerHTML = createdElement.innerHTML + REACTION_TYPES[key].renderedIcon;
-
summaryList.appendChild(createdElement);
- this._initReactionCountButton(createdElement, objectId);
-
triggerChange = true;
}
}, this);
+
+ window[(summaryList.childElementCount > 0 ? 'elShow' : 'elHide')](summaryList);
}.bind(this));
if (triggerChange) {
* @param {object} elementData
*/
_initReactionCountButtons: function(element, elementData) {
- if (this._options.isSingleItem) {
- var summaryList = elBySel(this._options.summaryListSelector);
- }
- else {
- var summaryList = elBySel(this._options.summaryListSelector, element);
- }
-
+ var summaryList = elBySel(this._options.summaryListSelector, this._options.isSingleItem ? undefined : element);
if (summaryList !== null) {
- var elements = elBySelAll('li', summaryList);
- for (var i = 0, length = elements.length; i < length; i++) {
- this._initReactionCountButton(elements[i], elementData.objectId);
- }
+ summaryList.addEventListener(WCF_CLICK_EVENT, this._showReactionOverlay.bind(this, elementData.objectId));
}
},
- /**
- * Initialized a specific reaction count button for an object.
- *
- * @param {element} element
- * @param {int} objectId
- */
- _initReactionCountButton: function(element, objectId) {
- element.addEventListener(WCF_CLICK_EVENT, this._showReactionOverlay.bind(this, objectId));
- },
-
/**
* Shows the reaction overly for a specific object.
*
}
this._containers = new Dictionary();
- this._details = new ObjectMap();
this._objectType = objectType;
this._cache = new Dictionary();
this._objects = new Dictionary();
continue;
}
+ objectId = ~~elData(element, 'object-id');
elementData = {
reactButton: null,
- objectId: ~~elData(element, 'object-id'),
+ objectId: objectId,
element: element
};
this._containers.set(DomUtil.identify(element), elementData);
this._initReactButton(element, elementData);
-
- if (!this._objects.has(~~elData(element, 'object-id'))) {
- var objects = [];
- }
- else {
- var objects = this._objects.get(~~elData(element, 'object-id'));
+
+ var objects = [];
+ if (this._objects.has(objectId)) {
+ objects = this._objects.get(objectId);
}
objects.push(elementData);
- this._objects.set(~~elData(element, 'object-id'), objects);
+ this._objects.set(objectId, objects);
triggerChange = true;
}
}
if (elementData.reactButton === null || elementData.reactButton.length === 0) {
- // the element may have no react button
+ // The element may have no react button.
return;
}
+ //noinspection JSUnresolvedVariable
if (Object.keys(REACTION_TYPES).length === 1) {
+ //noinspection JSUnresolvedVariable
var reaction = REACTION_TYPES[Object.keys(REACTION_TYPES)[0]];
elementData.reactButton.title = reaction.title;
var textSpan = elBySel('.invisible', elementData.reactButton);
if (reactionTypeID) {
elementData.reactButton.classList.add('active');
elData(elementData.reactButton, 'reaction-type-id', reactionTypeID);
- } else {
+ }
+ else {
elData(elementData.reactButton, 'reaction-type-id', 0);
elementData.reactButton.classList.remove('active');
}
},
_markReactionAsActive: function() {
- var reactionTypeID;
+ var reactionTypeID = null;
this._objects.get(this._popoverCurrentObjectId).forEach(function (element) {
if (element.reactButton !== null) {
- reactionTypeID = elData(element.reactButton, 'reaction-type-id');
+ reactionTypeID = ~~elData(element.reactButton, 'reaction-type-id');
}
});
- if (reactionTypeID === undefined) {
+ if (reactionTypeID === null) {
throw new Error("Unable to find react button for current popover.");
}
- // clear old active state
- var elements = elBySelAll('.reactionTypeButton.active', this._getPopover());
- for (var i = 0, length = elements.length; i < length; i++) {
- elements[i].classList.remove('active');
- }
+ // Clear the old active state.
+ elBySelAll('.reactionTypeButton.active', this._getPopover(), function(element) {
+ element.classList.remove('active');
+ });
- if (reactionTypeID != 0) {
- elBySel('.reactionTypeButton[data-reaction-type-id="'+reactionTypeID+'"]', this._getPopover()).classList.add('active');
+ if (reactionTypeID) {
+ elBySel('.reactionTypeButton[data-reaction-type-id="' + reactionTypeID + '"]', this._getPopover()).classList.add('active');
}
},
*
* @param {int} objectId
* @param {Element} element
+ * @param {?Event} event
*/
_toggleReactPopover: function(objectId, element, event) {
if (event !== null) {
event.preventDefault();
event.stopPropagation();
}
-
+
+ //noinspection JSUnresolvedVariable
if (Object.keys(REACTION_TYPES).length === 1) {
+ //noinspection JSUnresolvedVariable
var reaction = REACTION_TYPES[Object.keys(REACTION_TYPES)[0]];
this._popoverCurrentObjectId = objectId;
* @param {Element} element container element
*/
_openReactPopover: function(objectId, element) {
- // first close old popover, if exists
if (this._popoverCurrentObjectId !== 0) {
this._closePopover();
}
});
if (this._options.isButtonGroupNavigation) {
- // find nav element
- var nav = element.closest('nav');
- nav.style.opacity = "1";
+ element.closest('nav').style.setProperty('opacity', '1', '');
}
this._getPopover().classList.remove('forceHide');
var reactionTypeItemSpan = elCreate('span');
reactionTypeItemSpan.classList = 'reactionTypeButtonTitle';
reactionTypeItemSpan.innerHTML = reactionType.title;
-
+
+ //noinspection JSUnresolvedVariable
reactionTypeItem.innerHTML = reactionType.renderedIcon;
reactionTypeItem.appendChild(reactionTypeItemSpan);
var sortedReactionTypes = [];
// convert our reaction type object to an array
+ //noinspection JSUnresolvedVariable
for (var key in REACTION_TYPES) {
- if (!REACTION_TYPES.hasOwnProperty(key)) continue;
- sortedReactionTypes.push(REACTION_TYPES[key]);
+ //noinspection JSUnresolvedVariable
+ if (REACTION_TYPES.hasOwnProperty(key)) {
+ //noinspection JSUnresolvedVariable
+ sortedReactionTypes.push(REACTION_TYPES[key]);
+ }
}
// sort the array
sortedReactionTypes.sort(function (a, b) {
+ //noinspection JSUnresolvedVariable
return a.showOrder - b.showOrder;
});
},
_ajaxSuccess: function(data) {
+ //noinspection JSUnresolvedVariable
this.countButtons.updateCountButtons(data.returnValues.objectID, data.returnValues.reactions);
- // update react button status
this._updateReactButton(data.returnValues.objectID, data.returnValues.reactionTypeID);
},
* likeable object
* @var ILikeObject
*/
- public $likeableObject = null;
+ public $likeableObject;
/**
* object type object
* @var ObjectType
*/
- public $objectType = null;
+ public $objectType;
/**
* like object type provider object
* @var ILikeObjectTypeProvider
*/
- public $objectTypeProvider = null;
+ public $objectTypeProvider;
/**
* reaction type for the reaction
* @var ReactionType
*/
- public $reactionType = null;
+ public $reactionType;
/**
* Validates parameters to fetch like details.
flex-wrap: wrap;
&:not(:first-child) {
- > .likesSummary,
+ > .reactionSummaryList,
> .messageFooterButtons,
> .messageFooterButtonsExtra {
margin-top: 20px;
}
}
- > .likesSummary {
+ > .reactionSummaryList {
flex: 0 1 auto;
@include wcfFontSmall;
}
}
-img.reactionType {
- width: 24px;
- height: 24px;
+.reactionType {
+ width: 20px;
+ height: 20px;
}
.reactionSummaryList {
- span.reactionCount::after {
- content: ' × ';
+ display: flex;
+ flex-wrap: wrap;
+ margin: -5px -5px 0 0;
+
+ .reactionCount{
+ @include wcfFontSmall;
+
+ &::before {
+ content: ' × ';
+ }
+ }
+
+ &.reactionSummaryListTiny .reactionType {
+ width: 16px;
+ height: 16px;
+ }
+}
+
+.reactCountButton {
+ color: $wcfContentDimmedText;
+ flex: 0 0 auto;
+ margin: 5px 5px 0 0;
+ white-space: nowrap;
+
+ &:hover {
+ color: $wcfContentText;
}
}
}
@include screen-md-down {
- padding: 5px 0px;
+ padding: 5px 0;
> ul > li.reactionTypeButton {
- margin: 0px;
+ margin: 0;
display: block;
padding: 5px 25px;
}
}
> ul > li.reactionTypeButton:first-child {
- margin-left: 0px;
+ margin-left: 0;
}
}
}
-li.reactCountButton {
- display: inline;
- padding: 5px;
- cursor: pointer;
- color: $wcfContentDimmedText;
- white-space: nowrap;
-}
-
-li.reactCountButton:hover {
- color: $wcfContentText;
-}
-
.reputationCounter {
color: $wcfContentDimmedText;
}
}
-.reactionSummaryListTiny {
- display: inline;
-
- li.reactCountButton > img {
- width: 16px;
- height: 16px;
- }
-
- span.reactionCount {
- @include wcfFontSmall;
- }
-
- li.reactCountButton {
- background-color: transparent;
- padding: 0px;
- }
-}
-
@include screen-sm-down {
.reactionStatusContainer {
display: none;
align-items: center;
}
}
-}
\ No newline at end of file
+}