Browse Source

Ticket #4226 - Reactions: Allow to switch between Icon/Emoji/Image based controls.

AntonLV 3 years ago
parent
commit
448837b8f9

+ 38 - 9
inc/classes/BxDolVoteReactions.php

@@ -60,8 +60,10 @@ class BxDolVoteReactions extends BxTemplVote
                 'name' => $sReaction,
                 'title' => $aReaction['LKey'],
                 'title_aux' => $aReaction['LKey2'],
+                'use' => isset($aData['use']) ? $aData['use'] : 'emoji',
                 'icon' => isset($aData['icon']) ? $aData['icon'] : '',
                 'emoji' => isset($aData['emoji']) ? $aData['emoji'] : '',
+                'image' => isset($aData['image']) ? $aData['image'] : '',
                 'color' => isset($aData['color']) ? $aData['color'] : '',
                 'weight' => isset($aData['weight']) ? $aData['weight'] : 1,
                 'default' => isset($aData['default']) ? $aData['default'] : '',
@@ -71,10 +73,12 @@ class BxDolVoteReactions extends BxTemplVote
         if(empty($sDefault) && !empty($this->_aDataList))
             $sDefault = current(array_keys($this->_aDataList));
 
-        $this->_aDataList[$this->_sDefault] = $this->_aDataList[$sDefault];
-        $this->_aDataList[$this->_sDefault]['icon'] = $this->_aDataList[$sDefault]['default'];
-        $this->_aDataList[$this->_sDefault]['emoji'] = '';
-        $this->_aDataList[$this->_sDefault]['color'] = '';
+        $this->_aDataList[$this->_sDefault] = array_merge($this->_aDataList[$sDefault], [
+            'icon' => $this->_aDataList[$sDefault]['default'],
+            'emoji' => '',
+            'image' => '',
+            'color' => ''
+        ]);
     }
     /**
      * Interface functions for outer usage
@@ -111,7 +115,7 @@ class BxDolVoteReactions extends BxTemplVote
     {
         $aReaction = isset($this->_aDataList[$sReaction]) ? $this->_aDataList[$sReaction] : $this->_aDataList[$this->_sDefault];
 
-    	return $aReaction['icon'] . ($bWithColor && !empty($aReaction['color']) ? ' sys-icon-emoji ' . $aReaction['color'] : ' sys-icon-emoji ');
+    	return $aReaction['icon'] . ($bWithColor && !empty($aReaction['color']) ? ' ' . $aReaction['color'] : '');
     }
     
     public function getEmoji($sReaction, $bWithColor = true)
@@ -121,6 +125,13 @@ class BxDolVoteReactions extends BxTemplVote
     	return $aReaction['emoji'];
     }
 
+    public function getImage($sReaction, $bWithColor = true)
+    {
+        $aReaction = isset($this->_aDataList[$sReaction]) ? $this->_aDataList[$sReaction] : $this->_aDataList[$this->_sDefault];
+
+    	return $aReaction['image'];
+    }
+
     /**
      * Actions functions
      */
@@ -199,21 +210,30 @@ class BxDolVoteReactions extends BxTemplVote
 
     protected function _returnVoteData($iObjectId, $iAuthorId, $iAuthorIp, $aData, $bVoted, $aParams = array())
     {
-        $aReactions = $this->getReactions();
+        $aReactions = $this->getReactions(true);
         $sReaction = $aData['reaction'];
 
         $bUndo = $this->isUndo();
         $bDisabled = $bVoted && !$bUndo;
 
         $aVote = $this->_getVote($iObjectId, true);
-        $aTrack = $bVoted ? $this->_getTrack($iObjectId, $iAuthorId) : array();
+        $aTrack = $bVoted ? $this->_getTrack($iObjectId, $iAuthorId) : [];
+
+        $sSwitchTo = $bVoted ? $sReaction : $this->_sDefault;
+
+        $sLabelUse = !empty($aReactions[$sSwitchTo]['use']) ? $aReactions[$sSwitchTo]['use'] : 'emoji';
+        $sLabelIcon = $this->_getIconDoWithTrack($bVoted, $aTrack);
+        if(!$bVoted && $sLabelUse != 'icon') {
+            $sLabelUse = 'icon';
+            $sLabelIcon = $this->_oTemplate->parseIcon($sLabelIcon);
+        }
 
         $sJsClick = '';
         if(!$bDisabled)
             $sJsClick = $bVoted && $bUndo ? $this->getJsClickDo($sReaction) : $this->getJsClick();
 
         $iTotalC = $iTotalS = 0;
-        foreach($aReactions as $sName) {
+        foreach(array_keys($aReactions) as $sName) {
             $iTotalC += (int)$aVote['count_' . $sName];
             $iTotalS += (int)$aVote['sum_' . $sName];
         }
@@ -226,8 +246,10 @@ class BxDolVoteReactions extends BxTemplVote
             'rate' => $aVote['rate_' . $sReaction],
             'count' => $iCount,
             'countf' => $iCount > 0 ? $this->_getCounterLabel($iCount, array('reaction' => $sReaction)) : '',
-            'label_icon' => $this->_getIconDoWithTrack($bVoted, $aTrack),
+            'label_use' => $sLabelUse,
+            'label_icon' => $sLabelIcon,
             'label_emoji' => $this->_getEmojiDoWithTrack($bVoted, $aTrack),
+            'label_image' => $this->_getImageDoWithTrack($bVoted, $aTrack),
             'label_title' => _t($this->_getTitleDoWithTrack($bVoted, $aTrack)),
             'label_click' => $sJsClick,
             'voted' => $bVoted,
@@ -255,6 +277,13 @@ class BxDolVoteReactions extends BxTemplVote
 
     	return $this->getEmoji($sReaction);
     }
+    
+    protected function _getImageDoWithTrack($bVoted, $aTrack = array())
+    {
+        $sReaction = $bVoted ? $aTrack['reaction'] : $this->_sDefault;
+
+    	return $this->getImage($sReaction);
+    }
 
     protected function _getTitleDoWithTrack($bVoted, $aTrack = array())
     {

+ 18 - 11
inc/js/classes/BxDolVoteReactions.js

@@ -88,17 +88,24 @@ BxDolVoteReactions.prototype.onVote = function (oLink, oData, onComplete)
 
     //--- Update Do button.
     oLink.each(function() {
-        if(oData && oData.label_icon){
-            $(this).find('.sys-action-do-icon .sys-icon').attr('class', 'sys-icon ' + oData.label_icon).html('');
-        }
-        if(oData && oData.label_emoji){
-            $(this).find('.sys-action-do-icon .sys-icon').html(oData.label_emoji);
-        }
-        else{
-            $(this).find('.sys-action-do-icon .sys-icon').removeClass('sys-icon-emoji');
-        }
-        
-        
+        if(oData && oData.label_use)
+            switch(oData.label_use) {
+                case 'icon':
+                    if($(this).find('.sys-action-do-icon .sys-icon').length != 0)
+                        $(this).find('.sys-action-do-icon .sys-icon').attr('class', 'sys-icon ' + oData.label_icon).html('');
+                    else
+                        $(this).find('.sys-action-do-icon').html(oData.label_icon);
+                    break;
+
+                case 'emoji':
+                    $(this).find('.sys-action-do-icon .sys-icon').attr('class', 'sys-icon sys-icon-emoji').html(oData.label_emoji);
+                    break;
+
+                case 'image':
+                    $(this).find('.sys-action-do-icon').html(oData.label_image);
+                    break;
+            }
+
         if(oData && oData.label_title) {
             $(this).attr('title', oData.label_title);
             $(this).find('.sys-action-do-text').html(oData.label_title);

+ 6 - 6
install/sql/system.sql

@@ -4293,12 +4293,12 @@ INSERT INTO `sys_form_pre_values`(`Key`, `Value`, `Order`, `LKey`, `LKey2`) VALU
 ('sys_report_types', 'other', 5, '_sys_pre_lists_report_types_other', '');
 
 INSERT INTO `sys_form_pre_values`(`Key`, `Value`, `Order`, `LKey`, `LKey2`, `Data`) VALUES
-('sys_vote_reactions', 'like', 1, '_sys_pre_lists_vote_reactions_like', '', 'a:5:{s:5:"emoji";s:4:"👍";s:4:"icon";s:0:"";s:5:"color";s:20:"sys-colored col-gray";s:6:"weight";s:1:"1";s:7:"default";s:9:"thumbs-up";}'),
-('sys_vote_reactions', 'love', 2, '_sys_pre_lists_vote_reactions_love', '', 'a:4:{s:5:"emoji";s:4:"💓";s:4:"icon";s:0:"";s:5:"color";s:20:"sys-colored col-red1";s:6:"weight";s:1:"1";}'),
-('sys_vote_reactions', 'joy', 3, '_sys_pre_lists_vote_reactions_joy', '', 'a:4:{s:5:"emoji";s:4:"😆";s:4:"icon";s:0:"";s:5:"color";s:20:"sys-colored col-red3";s:6:"weight";s:1:"1";}'),
-('sys_vote_reactions', 'surprise', 4, '_sys_pre_lists_vote_reactions_surprise', '', 'a:4:{s:5:"emoji";s:4:"😲";s:4:"icon";s:0:"";s:5:"color";s:20:"sys-colored col-red3";s:6:"weight";s:1:"1";}'),
-('sys_vote_reactions', 'sadness', 5, '_sys_pre_lists_vote_reactions_sadness', '', 'a:4:{s:5:"emoji";s:4:"😥";s:4:"icon";s:0:"";s:5:"color";s:20:"sys-colored col-red3";s:6:"weight";s:1:"1";}'),
-('sys_vote_reactions', 'anger', 6, '_sys_pre_lists_vote_reactions_anger', '', 'a:4:{s:5:"emoji";s:4:"😠";s:4:"icon";s:0:"";s:5:"color";s:20:"sys-colored col-red3";s:6:"weight";s:1:"1";}');
+('sys_vote_reactions', 'like', 1, '_sys_pre_lists_vote_reactions_like', '', 'a:7:{s:3:"use";s:5:"emoji";s:5:"emoji";s:4:"👍";s:4:"icon";s:12:"fa-thumbs-up";s:5:"image";s:904:"<svg aria-hidden="true" fill="none" stroke="currentColor" stroke-width="1.5" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="M6.633 10.5c.806 0 1.533-.446 2.031-1.08a9.041 9.041 0 012.861-2.4c.723-.384 1.35-.956 1.653-1.715a4.498 4.498 0 00.322-1.672V3a.75.75 0 01.75-.75A2.25 2.25 0 0116.5 4.5c0 1.152-.26 2.243-.723 3.218-.266.558.107 1.282.725 1.282h3.126c1.026 0 1.945.694 2.054 1.715.045.422.068.85.068 1.285a11.95 11.95 0 01-2.649 7.521c-.388.482-.987.729-1.605.729H13.48c-.483 0-.964-.078-1.423-.23l-3.114-1.04a4.501 4.501 0 00-1.423-.23H5.904M14.25 9h2.25M5.904 18.75c.083.205.173.405.27.602.197.4-.078.898-.523.898h-.908c-.889 0-1.713-.518-1.972-1.368a12 12 0 01-.521-3.507c0-1.553.295-3.036.831-4.398C3.387 10.203 4.167 9.75 5 9.75h1.053c.472 0 .745.556.5.96a8.958 8.958 0 00-1.302 4.665c0 1.194.232 2.333.654 3.375z" stroke-linecap="round" stroke-linejoin="round"></path></svg>";s:5:"color";s:20:"sys-colored col-gray";s:6:"weight";s:1:"1";s:7:"default";s:9:"thumbs-up";}'),
+('sys_vote_reactions', 'love', 2, '_sys_pre_lists_vote_reactions_love', '', 'a:6:{s:3:"use";s:5:"emoji";s:5:"emoji";s:4:"💓";s:4:"icon";s:8:"fa-heart";s:5:"image";s:499:"<svg aria-hidden="true" fill="currentColor" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="M11.645 20.91l-.007-.003-.022-.012a15.247 15.247 0 01-.383-.218 25.18 25.18 0 01-4.244-3.17C4.688 15.36 2.25 12.174 2.25 8.25 2.25 5.322 4.714 3 7.688 3A5.5 5.5 0 0112 5.052 5.5 5.5 0 0116.313 3c2.973 0 5.437 2.322 5.437 5.25 0 3.925-2.438 7.111-4.739 9.256a25.175 25.175 0 01-4.244 3.17 15.247 15.247 0 01-.383.219l-.022.012-.007.004-.003.001a.752.752 0 01-.704 0l-.003-.001z"></path></svg>";s:5:"color";s:20:"sys-colored col-red1";s:6:"weight";s:1:"1";}'),
+('sys_vote_reactions', 'joy', 3, '_sys_pre_lists_vote_reactions_joy', '', 'a:6:{s:3:"use";s:5:"emoji";s:5:"emoji";s:4:"😆";s:4:"icon";s:15:"fa-laugh-squint";s:5:"image";s:789:"<svg aria-hidden="true" fill="currentColor" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path clip-rule="evenodd" d="M12 2.25c-5.385 0-9.75 4.365-9.75 9.75s4.365 9.75 9.75 9.75 9.75-4.365 9.75-9.75S17.385 2.25 12 2.25zm-2.625 6c-.54 0-.828.419-.936.634a1.96 1.96 0 00-.189.866c0 .298.059.605.189.866.108.215.395.634.936.634.54 0 .828-.419.936-.634.13-.26.189-.568.189-.866 0-.298-.059-.605-.189-.866-.108-.215-.395-.634-.936-.634zm4.314.634c.108-.215.395-.634.936-.634.54 0 .828.419.936.634.13.26.189.568.189.866 0 .298-.059.605-.189.866-.108.215-.395.634-.936.634-.54 0-.828-.419-.936-.634a1.96 1.96 0 01-.189-.866c0-.298.059-.605.189-.866zm2.023 6.828a.75.75 0 10-1.06-1.06 3.75 3.75 0 01-5.304 0 .75.75 0 00-1.06 1.06 5.25 5.25 0 007.424 0z" fill-rule="evenodd"></path></svg>";s:5:"color";s:20:"sys-colored col-red3";s:6:"weight";s:1:"1";}'),
+('sys_vote_reactions', 'surprise', 4, '_sys_pre_lists_vote_reactions_surprise', '', 'a:6:{s:3:"use";s:5:"emoji";s:5:"emoji";s:4:"😲";s:4:"icon";s:11:"fa-surprise";s:5:"image";s:551:"<svg aria-hidden="true" fill="currentColor" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="M9.375 3a1.875 1.875 0 000 3.75h1.875v4.5H3.375A1.875 1.875 0 011.5 9.375v-.75c0-1.036.84-1.875 1.875-1.875h3.193A3.375 3.375 0 0112 2.753a3.375 3.375 0 015.432 3.997h3.943c1.035 0 1.875.84 1.875 1.875v.75c0 1.036-.84 1.875-1.875 1.875H12.75v-4.5h1.875a1.875 1.875 0 10-1.875-1.875V6.75h-1.5V4.875C11.25 3.839 10.41 3 9.375 3zM11.25 12.75H3v6.75a2.25 2.25 0 002.25 2.25h6v-9zM12.75 12.75v9h6.75a2.25 2.25 0 002.25-2.25v-6.75h-9z"></path></svg>";s:5:"color";s:20:"sys-colored col-red3";s:6:"weight";s:1:"1";}'),
+('sys_vote_reactions', 'sadness', 5, '_sys_pre_lists_vote_reactions_sadness', '', 'a:6:{s:3:"use";s:5:"emoji";s:5:"emoji";s:4:"😥";s:4:"icon";s:11:"fa-sad-tear";s:5:"image";s:736:"<svg aria-hidden="true" fill="currentColor" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path clip-rule="evenodd" d="M16.5 4.478v.227a48.816 48.816 0 013.878.512.75.75 0 11-.256 1.478l-.209-.035-1.005 13.07a3 3 0 01-2.991 2.77H8.084a3 3 0 01-2.991-2.77L4.087 6.66l-.209.035a.75.75 0 01-.256-1.478A48.567 48.567 0 017.5 4.705v-.227c0-1.564 1.213-2.9 2.816-2.951a52.662 52.662 0 013.369 0c1.603.051 2.815 1.387 2.815 2.951zm-6.136-1.452a51.196 51.196 0 013.273 0C14.39 3.05 15 3.684 15 4.478v.113a49.488 49.488 0 00-6 0v-.113c0-.794.609-1.428 1.364-1.452zm-.355 5.945a.75.75 0 10-1.5.058l.347 9a.75.75 0 101.499-.058l-.346-9zm5.48.058a.75.75 0 10-1.498-.058l-.347 9a.75.75 0 001.5.058l.345-9z" fill-rule="evenodd"></path></svg>";s:5:"color";s:20:"sys-colored col-red3";s:6:"weight";s:1:"1";}'),
+('sys_vote_reactions', 'anger', 6, '_sys_pre_lists_vote_reactions_anger', '', 'a:6:{s:3:"use";s:5:"emoji";s:5:"emoji";s:4:"😠";s:4:"icon";s:8:"fa-angry";s:5:"image";s:858:"<svg aria-hidden="true" fill="currentColor" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path clip-rule="evenodd" d="M12 2.25c-5.385 0-9.75 4.365-9.75 9.75s4.365 9.75 9.75 9.75 9.75-4.365 9.75-9.75S17.385 2.25 12 2.25zm-2.625 6c-.54 0-.828.419-.936.634a1.96 1.96 0 00-.189.866c0 .298.059.605.189.866.108.215.395.634.936.634.54 0 .828-.419.936-.634.13-.26.189-.568.189-.866 0-.298-.059-.605-.189-.866-.108-.215-.395-.634-.936-.634zm4.314.634c.108-.215.395-.634.936-.634.54 0 .828.419.936.634.13.26.189.568.189.866 0 .298-.059.605-.189.866-.108.215-.395.634-.936.634-.54 0-.828-.419-.936-.634a1.96 1.96 0 01-.189-.866c0-.298.059-.605.189-.866zm-4.34 7.964a.75.75 0 01-1.061-1.06 5.236 5.236 0 013.73-1.538 5.236 5.236 0 013.695 1.538.75.75 0 11-1.061 1.06 3.736 3.736 0 00-2.639-1.098 3.736 3.736 0 00-2.664 1.098z" fill-rule="evenodd"></path></svg>";s:5:"color";s:20:"sys-colored col-red3";s:6:"weight";s:1:"1";}');
 
 INSERT INTO `sys_form_pre_values`(`Key`, `Value`, `Order`, `LKey`, `LKey2`, `Data`) VALUES
 ('sys_relations', '1', 1, '_sys_pre_lists_relations_husband', '', 'a:1:{i:0;s:1:"2";}'),

+ 5 - 0
template/css/vote.css

@@ -1,3 +1,8 @@
+.bx-vote .sys-action-element-holder .sys-action-do-icon svg,
+.bx-vote-counter .bx-vote-counter-label .bx-vote-counter-icon svg {
+    width: 1.25rem;
+    height: 1.25rem;
+}
 .bx-vote .bx-vote-counter .bx-vote-counter-label {
     padding: 0;
 }

+ 102 - 19
template/scripts/BxBaseVoteReactions.php

@@ -426,22 +426,46 @@ class BxBaseVoteReactions extends BxDolVoteReactions
     protected function _getDoVoteLabel($aParams = array())
     {
     	$bVoted = isset($aParams['is_voted']) && (bool)$aParams['is_voted'] === true;
+        $aTrack = $bVoted ? $aParams['track'] : [];
 
+        $sReaction = $bVoted ? $aTrack['reaction'] : $this->_sDefault;
+        $aReaction = $this->getReaction($sReaction);
+
+        $sUse = !empty($aReaction['use']) ? $aReaction['use'] : 'emoji';
+        if(!$bVoted && !empty($aReaction['default']))
+            $sUse = 'icon';
+        
         return $this->_oTemplate->parseHtmlByContent($this->_getTmplContentDoActionLabel(), array(
             'style_prefix' => $this->_sStylePrefix,
-            'bx_if:show_icon' => array(
+            'bx_if:show_icon' => [
                 'condition' => isset($aParams['show_do_vote_icon']) && (bool)$aParams['show_do_vote_icon'] === true,
-                'content' => array(
+                'content' => [
                     'style_prefix' => $this->_sStylePrefix,
-                    'name' => $this->_getIconDoWithTrack($bVoted, $aParams['track']),
-                    'emoji' => $this->_getEmojiDoWithTrack($bVoted, $aParams['track'])
-                )
-            ),
+                    'bx_if:show_as_icon' => [
+                        'condition' => $sUse == 'icon',
+                        'content' => [
+                            'name' => $sUse == 'icon' ? $this->_getIconDoWithTrack($bVoted, $aTrack) : '',
+                        ]
+                    ],
+                    'bx_if:show_as_emoji' => [
+                        'condition' => $sUse == 'emoji',
+                        'content' => [
+                            'emoji' => $sUse == 'emoji' ? $this->_getEmojiDoWithTrack($bVoted, $aTrack) : '',
+                        ]
+                    ],
+                    'bx_if:show_as_image' => [
+                        'condition' => $sUse == 'image',
+                        'content' => [
+                            'image' => $sUse == 'image' ? $this->_getImageDoWithTrack($bVoted, $aTrack) : '',
+                        ]
+                    ],
+                ]
+            ],
             'bx_if:show_text' => array(
                 'condition' => isset($aParams['show_do_vote_label']) && (bool)$aParams['show_do_vote_label'] === true,
                 'content' => array(
                     'style_prefix' => $this->_sStylePrefix,
-                    'text' => _t($this->_getTitleDoWithTrack($bVoted, $aParams['track']))
+                    'text' => _t($this->_getTitleDoWithTrack($bVoted, $aTrack))
                 )
             )
         ));
@@ -475,6 +499,9 @@ class BxBaseVoteReactions extends BxDolVoteReactions
     protected function _getCounterLabel($iCount, $aParams = array())
     {
         $sReaction = !empty($aParams['reaction']) ? $aParams['reaction'] : $this->_sDefault;
+        $aReaction = $this->getReaction($sReaction);
+
+        $sUse = !empty($aReaction['use']) ? $aReaction['use'] : 'emoji';
 
         return $this->_oTemplate->parseHtmlByContent($this->_getTmplContentCounterLabel(), array(
             'style_prefix' => $this->_sStylePrefix,
@@ -482,8 +509,24 @@ class BxBaseVoteReactions extends BxDolVoteReactions
                 'condition' => !isset($aParams['show_counter_label_icon']) || (bool)$aParams['show_counter_label_icon'] === true,
                 'content' => array(
                     'style_prefix' => $this->_sStylePrefix,
-                    'name' => $this->getIcon($sReaction),
-                    'emoji' => $this->getEmoji($sReaction),
+                    'bx_if:show_as_icon' => [
+                        'condition' => $sUse == 'icon',
+                        'content' => [
+                            'name' => $sUse == 'icon' ? $this->getIcon($sReaction) : '',
+                        ]
+                    ],
+                    'bx_if:show_as_emoji' => [
+                        'condition' => $sUse == 'emoji',
+                        'content' => [
+                            'emoji' => $sUse == 'emoji' ? $this->getEmoji($sReaction) : '',
+                        ]
+                    ],
+                    'bx_if:show_as_image' => [
+                        'condition' => $sUse == 'image',
+                        'content' => [
+                            'image' => $sUse == 'image' ? $this->getImage($sReaction) : '',
+                        ]
+                    ],
                     'title_attr' => bx_html_attribute(_t($this->_aDataList[$sReaction]['title'])),
                 )
             ),
@@ -502,6 +545,8 @@ class BxBaseVoteReactions extends BxDolVoteReactions
         if(!isset($aParams['reaction']))
             return $this->_getVotedBySummary($aParams);
 
+        $aReactions = $this->getReactions(true);
+
         $bSummary = $aParams['reaction'] == 'summary';
 
         $aBrowseParams = array('type' => 'by', 'object_id' => $this->getId());
@@ -514,17 +559,40 @@ class BxBaseVoteReactions extends BxDolVoteReactions
         foreach($aValues as $mValue) {
             $mValue = is_array($mValue) ? $mValue : array('author_id' => (int)$mValue, 'reaction' => '');
 
+            $aTmplReaction = [];
+            if($bSummary) {
+                $sUse = !empty($aReactions[$mValue['reaction']]['use']) ? $aReactions[$mValue['reaction']]['use'] : 'emoji';
+
+                $aTmplReaction = [
+                    'style_prefix' => $this->_sStylePrefix,
+                    'bx_if:show_as_icon' => [
+                        'condition' => $sUse == 'icon',
+                        'content' => [
+                            'name' => $sUse == 'icon' ? $this->getIcon($mValue['reaction']) : '',
+                        ]
+                    ],
+                    'bx_if:show_as_emoji' => [
+                        'condition' => $sUse == 'emoji',
+                        'content' => [
+                            'emoji' => $sUse == 'emoji' ? $this->getEmoji($mValue['reaction']) : '',
+                        ]
+                    ],
+                    'bx_if:show_as_image' => [
+                        'condition' => $sUse == 'image',
+                        'content' => [
+                            'image' => $sUse == 'image' ? $this->getImage($mValue['reaction']) : '',
+                        ]
+                    ],
+                ];
+            }
+            
             list($sUserName, $sUserUrl, $sUserIcon, $sUserUnit) = $this->_getAuthorInfo($mValue['author_id']);
             $aTmplUsers[] = array(
                 'style_prefix' => $this->_sStylePrefix,
                 'user_unit' => $sUserUnit,
                 'bx_if:show_reaction' => array(
                     'condition' => $bSummary,
-                    'content' => array(
-                        'style_prefix' => $this->_sStylePrefix,
-                        'icon' => $bSummary ? $this->getIcon($mValue['reaction']) : '',
-                        'emoji' => $bSummary ? $this->getEmoji($mValue['reaction']) : ''
-                    )
+                    'content' => $aTmplReaction
                 )
             );
         }
@@ -544,21 +612,36 @@ class BxBaseVoteReactions extends BxDolVoteReactions
         $sJsObject = $this->getJsObjectName();
 
         $sTxtSummary = _t('_vote_do_by_summary');
-        $aReactions = array_merge(array('summary'), $this->getReactions());
+        $aReactions = array_merge(['summary' => []], $this->getReactions(true));
 
         $aMenuItems = array();
         $aTmplVarsLists = array();
-        foreach ($aReactions as $sReaction) {
+        foreach ($aReactions as $sReaction => $aReaction) {
             if($sReaction == $this->_sDefault)
                 continue;
 
             $bSummary = $sReaction == 'summary';
+            $sUse = !empty($aReaction['use']) ? $aReaction['use'] : 'emoji';
+            
+            $sIcon = '';
+            switch($sUse) {
+                case 'icon':
+                    $sIcon = $this->_oTemplate->parseIcon($this->getIcon($sReaction));
+                    break;
+
+                case 'emoji':
+                    $sIcon = $this->getEmoji($sReaction);
+                    break;
+
+                case 'image':
+                    $sIcon = $this->getImage($sReaction);
+                    break;
+            }
 
-            $sName = $this->_sStylePrefix . '-' . $sReaction;
-            $sEmoji = $this->getEmoji($sReaction);
-            $sTitle = !$bSummary ? $this->_oTemplate->parseIcon($sEmoji ? $sEmoji : $this->getIcon($sReaction)) : $sTxtSummary;
+            $sTitle = !$bSummary ? $sIcon : $sTxtSummary;
             $sTitleAttr = !$bSummary ? _t('_vote_do_by_x_reaction', _t($this->_aDataList[$sReaction]['title'])) : $sTxtSummary;
 
+            $sName = $this->_sStylePrefix . '-' . $sReaction;
             $aMenuItems[] = array('id' => $sName, 'name' => $sName, 'class' => '', 'link' => 'javascript:void(0)', 'onclick' => 'javascript:' . $sJsObject . '.changeVotedBy(this, \'' . $sReaction . '\')', 'target' => '_self', 'title' => $sTitle, 'title_attr' => $sTitleAttr, 'active' => 1);
 
             $aTmplVarsLists[] = array(

+ 14 - 3
template/scripts/BxBaseVoteReactionsMenuDo.php

@@ -42,8 +42,19 @@ class BxBaseVoteReactionsMenuDo extends BxTemplMenu
             if($sName == $sDefault)
                 continue;
 
-            $sEmoji = $this->_oObject->getEmoji($sName);
-            
+            $sIcon = '';
+            switch($aReaction['use']) {
+                case 'icon':
+                    $sIcon = $this->_oObject->getIcon($sName);
+                    break;
+                case 'emoji':
+                    $sIcon = $this->_oObject->getEmoji($sName);
+                    break;
+                case 'image':
+                    $sIcon = $this->_oObject->getImage($sName);
+                    break;
+            }
+
             $aMenuItems[] = array(
                 'id' => $sName, 
                 'name' => $sName, 
@@ -52,7 +63,7 @@ class BxBaseVoteReactionsMenuDo extends BxTemplMenu
                 'onclick' => 'javascript:' . $this->_oObject->getJsClickDo($sName, $this->_iValue), 
                 'target' => '_self', 
                 'title' => _t($aReaction['title']), 
-                'icon' => $sEmoji != '' ? $sEmoji : $this->_oObject->getIcon($sName), 
+                'icon' => $sIcon,
                 'active' => 1
             );
         }

+ 9 - 1
template/vote_by_list_reactions.html

@@ -5,7 +5,15 @@
                 <div class="__style_prefix__-by-item bx-def-padding-sec-topbottom bx-clearfix">
                     <div class="__style_prefix__-bi-user">__user_unit__</div>
                     <bx_if:show_reaction>
-                        <div class="__style_prefix__-bi-icon"><i class="sys-icon __icon__">__emoji__</i></div>
+                        <div class="__style_prefix__-bi-icon">
+                            <bx_if:show_as_icon>
+                                <i class="sys-icon __name__"></i>
+                            </bx_if:show_as_icon>
+                            <bx_if:show_as_emoji>
+                                <i class="sys-icon sys-icon-emoji">__emoji__</i>
+                            </bx_if:show_as_emoji>
+                            <bx_if:show_as_image>__image__</bx_if:show_as_image>
+                        </div>
                     </bx_if:show_reaction>
                 </div>
             </bx_repeat:list>

+ 7 - 1
template/vote_counter_label_reactions.html

@@ -1,7 +1,13 @@
 <span class="__style_prefix__-counter-label flex items-center text-sm font-normal p-1">
     <bx_if:show_icon>
         <span class="sys-action-counter-icon __style_prefix__-counter-icon relative flex items-center justify-center ring-1  h-6 w-6 ring-white dark:ring-gray-700 h-6 w-6 bg-gray-200 dark:bg-gray-700 rounded-full">
-            <i class="sys-icon __name__">__emoji__</i>
+            <bx_if:show_as_icon>
+                <i class="sys-icon __name__"></i>
+            </bx_if:show_as_icon>
+            <bx_if:show_as_emoji>
+                <i class="sys-icon sys-icon-emoji">__emoji__</i>
+            </bx_if:show_as_emoji>
+            <bx_if:show_as_image>__image__</bx_if:show_as_image>
         </span>
     </bx_if:show_icon>
     <bx_if:show_text>

+ 16 - 1
template/vote_do_vote_label_reactions.html

@@ -1 +1,16 @@
-<span class="sys-action-do __style_prefix__-do bx-def-valign-center"><bx_if:show_icon><span class="sys-action-do-icon __style_prefix__-do-icon bx-def-align-center"><i class="sys-icon __name__">__emoji__</i></span></bx_if:show_icon><bx_if:show_text><span class="sys-action-do-text __style_prefix__-do-text bx-def-margin-sec-left-auto">__text__</span></bx_if:show_text></span>
+<span class="sys-action-do __style_prefix__-do bx-def-valign-center">
+    <bx_if:show_icon>
+        <span class="sys-action-do-icon __style_prefix__-do-icon bx-def-align-center">
+            <bx_if:show_as_icon>
+                <i class="sys-icon __name__"></i>
+            </bx_if:show_as_icon>
+            <bx_if:show_as_emoji>
+                <i class="sys-icon sys-icon-emoji">__emoji__</i>
+            </bx_if:show_as_emoji>
+            <bx_if:show_as_image>__image__</bx_if:show_as_image>
+        </span>
+    </bx_if:show_icon>
+    <bx_if:show_text>
+        <span class="sys-action-do-text __style_prefix__-do-text bx-def-margin-sec-left-auto">__text__</span>
+    </bx_if:show_text>
+</span>