UNPKG

node-red-contrib-chatbot

Version:

REDBot a Chat bot for a full featured chat bot for Telegram, Facebook Messenger and Slack. Almost no coding skills required

1,125 lines (1,044 loc) 61.4 kB
<script type="text/javascript"> $.fn.RB_setComboWithPlatformLabels = function(value) { var combo = $(this); $(this).val(value); var selected = $('option[value=' + value + ']', this); combo .attr('class') .split(' ') .forEach(function(className) { if (className.indexOf('platform-') !== -1) { combo.removeClass(className); } }); if (selected != null) { combo.addClass(selected.attr('class')); } }; $.fn.RB_comboWithPlatformLabels = function() { $(this) .change(function() { var combo = $(this); var selected = $('option[value=' + combo.val() + ']', this); combo .attr('class') .split(' ') .forEach(function(className) { if (className.indexOf('platform-') !== -1) { combo.removeClass(className); } }); if (selected != null) { combo.addClass(selected.attr('class')); } }); }; $.fn.RB_OptionsEditor = function(command, options) { var container = $(this); var defaultOptions = { label: 'Options', labelAdd: 'add' }; if (arguments.length === 1 && typeof arguments[0] === 'object') { options = $.extend({}, defaultOptions, arguments[0]); command = 'init'; } else if (arguments.length === 0) { command = 'init'; options = $.extend({}, defaultOptions); } else if (arguments.length === 1 && arguments[0] === 'value') { command = 'get_value'; } else if (arguments.length === 2 && arguments[0] === 'value') { command = 'set_value'; } var addRow = function(value, label) { var count = $('.option', container); $('<div class="option"/>').css('marginTop','5px') .append('<div style="display:inline-block;width:6%;" class="order">' + (count.length + 1) + '.</div>') .append($('<input style="width:35%" class="node-input-rule-type" type="text" name="value" placeholder="Value" value="' + value + '"/>')) .append($('<input style="width:48%;margin-left: 5%" class="node-input-rule-type" type="text" name="label" placeholder="Label" value="' + label + '"/>')) .append('<a href="#" class="btn-remove" style="width:5%;display:inline-block;"><i class="fa fa-times"></i></a>') .appendTo($('.options', container)); }; switch(command) { case 'init': container .addClass('rb-options-editor') .on('click', '.btn-remove', function() { $(this).parents('.option').remove(); $('.option', container).each(function(idx, item) { $('.order', item).html(idx + 1); }); }); $('<div class="control-description"/>') .html(options.label) .appendTo(container); $('<div class="options"/>') .appendTo(container); $('<div class="button"/>') .append('<a class="btn-add" href="#">' + options.labelAdd+ '</a>') .appendTo(container); $('a.btn-add', container) .click(function(e) { e.preventDefault(); addRow('', ''); }); break; case 'get_value': var values = []; $('.option', container).each(function(idx, item) { var value = $('input[name=value]', item).val(); var label = $('input[name=label]', item).val(); if (value === '' && label !== '') { value = label; } else if (value !== '' && label === '') { label = value; } if (value !== '' && label !== '') { values.push({ value: value, label: label }); } }); return values; case 'set_value': $('.options').empty(); $(arguments[1]).each(function(idx, option) { addRow(option.value, option.label); }); break; } return container; }; $.fn.RB_setElementData = function(obj, options) { options = options || {}; options.badges = options.badges !== false; var container = $(this); var select = $('select[name=type]', container).val(obj.type); var panel = $('.panel-' + obj.type, container).show(); var element = $.RedBot.elementTypes.findElement(obj.type); if (element != null && options.badges) { select.attr('class', element.className); } $('input[name="label"]', panel).val(obj.label); $('input[name="name"]', panel).val(obj.name); $('input[name="value"]', panel).val(obj.value); $('input[name="placeholder"]', panel).val(obj.placeholder); $('input[name="hint"]', panel).val(obj.hint); $('select[name="subtype"]', panel).val(obj.subtype); $('input[name="max_length"]', panel).val(obj.maxLength); $('input[name="min_length"]', panel).val(obj.minLength); $('input[name="optional"]', panel).attr('checked', obj.optional === true); $('.container-options', panel).RB_OptionsEditor('value', obj.options); return container; }; $.fn.RB_setButtonData = function(obj, options) { options = options || {}; options.badges = options.badges !== false; var container = $(this); var availablePlatforms = $.isArray(container.data('platforms')) ? container.data('platforms') : ['facebook', 'telegram']; var select = $('select[name=type]', container).val(obj.type); var panel = $('.panel-' + obj.type, container).show(); var button = $.RedBot.buttonTypes.findButton(obj.type); // update badges of select with intersection of available platforms and button compatibility if (button != null && options.badges) { $.RedBot.supportedBy($('.type-badges', container), $.RedBot.intersect(availablePlatforms, button.platforms)); //select.attr('class', $.RedBot.platformClass('select', $.RedBot.intersect(availablePlatforms, button.platforms))); } else { //select.attr('class', ''); $('.type-badges', container).empty(); } $('input[name=label]', panel).val(obj.label); $('input[name=url]', panel).val(obj.url); $('input[name=value]', panel).val(obj.value); $('input[name=number]', panel).val(obj.number); $('input[name=answer]', panel).val(obj.answer); $('input[name=alert]', panel).attr('checked', obj.alert === true); $('select[name=webview_height_ratio]', panel).val(obj.webViewHeightRatio); $('select[name=style]', panel).val(obj.style); $('input[name=messenger_extensions]').attr('checked', obj.extensions === true); return container; }; $.fn.RB_getElementData = function() { var container = $(this); var type = $('select[name="type"]', container); var panel = $('.panel-' + type.val(), container); var label = $('input[name="label"]', panel); var name = $('input[name="name"]', panel); var value = $('input[name="value"]', panel); var placeholder = $('input[name="placeholder"]', panel); var hint = $('input[name="hint"]', panel); var subtype = $('select[name="subtype"]', panel); var maxLength = $('input[name="max_length"]', panel); var minLength = $('input[name="min_length"]', panel); var optional = $('input[name="optional"]', panel); var options = $('.container-options', panel); var result = null; switch(type.val()) { case 'text': case 'textarea': result = { type: type.val(), label: label.val(), name: name.val(), value: value.val(), placeholder: placeholder.val(), hint: hint.val(), optional: optional.is(':checked') }; if (subtype.val() !== '') { result.subtype = subtype.val(); } if (!isNaN(parseInt(maxLength.val(), 10))) { result.maxLength = parseInt(maxLength.val(), 10); } if (!isNaN(parseInt(minLength.val(), 10))) { result.minLength = parseInt(minLength.val(), 10); } break; case 'select': result = { type: 'select', label: label.val(), name: name.val(), options: options.RB_OptionsEditor('value') }; break; } return result; }; $.fn.RB_getButtonData = function() { var container = $(this); var type = $('select[name="type"]', container); var panel = $('.panel-' + type.val(), container); var label = $('input[name="label"]', panel); var url = $('input[name="url"]', panel); var value = $('input[name="value"]', panel); var number = $('input[name="number"]', panel); var answer = $('input[name="answer"]', panel); var alert = $('input[name="alert"]', panel); var style = $('select[name="style"]', panel); var messengerExtensions = $('input[name="messenger_extensions"]', panel); var webViewHeight = $('select[name="webview_height_ratio"]', panel); var result = null; switch(type.val()) { case 'keyboardButton': result = { type: 'keyboardButton', label: label.val() }; break; case 'url': result = { type: 'url', label: label.val(), url: url.val(), webViewHeightRatio: webViewHeight.val(), extensions: messengerExtensions.is(':checked'), answer: answer.val(), alert: alert.is(':checked') }; break; case 'call': result = { type: 'call', label: label.val(), number: number.val() }; break; case 'postback': result = { type: 'postback', label: label.val(), value: value.val(), answer: answer.val(), alert: alert.is(':checked'), style: style.val() }; break; case 'dialog': result = { type: 'dialog', label: label.val(), value: value.val(), answer: answer.val(), alert: alert.is(':checked'), style: style.val() }; break; case 'quick-reply': result = { type: 'quick-reply', label: label.val(), value: value.val(), url: url.val() }; break; case 'newline': result = { type: 'newline' }; break; case 'location': result = { type: 'location' }; break; case 'share': result = { type: 'share' }; break; case 'logout': result = { type: 'logout' }; break; case 'login': result = { type: 'login', url: url.val() }; break; case 'phone': result = { type: 'phone' }; break; case 'email': result = { type: 'email' }; break; } return result; }; $.fn.RB_hasPlatform = function(platform, platforms) { platform = platform instanceof Array ? platform : [platform]; var hasMatch = false; for(var idx = 0; idx < platform.length; idx++) { if (platforms.indexOf(platform[idx]) !== -1) { hasMatch = true; } } return hasMatch ? $(this) : $(); }; $.fn.RB_mountButtonDialog = function(options) { options = options || {}; options.types = options.types != null ? options.types : ['url', 'postback', 'call', 'share', 'login', 'newline', 'logout', 'location', 'quick-reply', 'dialog', 'key', 'email', 'phone']; options.platforms = options.platforms != null ? options.platforms : ['facebook', 'telegram']; options.badges = options.badges !== false; var container = $(this); // store available platforms in the container container.data('platforms', options.platforms); var main = $('<div/>').appendTo(container); var cx = options.badges ? $.RedBot.platformClass : function() { return ''; }; var selectButtonType = $('<select name="type"/>', { style:"width:200px; margin-left: 5px; text-align: center;" }) .attr('placeholder', 'Select button type') .change(function() { var type = $(this).val(); $('.panel', container).hide(); $('.panel-' + type, container).show(); // find the right button var button = $.RedBot.buttonTypes.findButton(type); // store class only if badges should be shown if (button != null && options.badges) { //$(this).attr('class', cx('select', $.RedBot.intersect(options.platforms, button.platforms))); $.RedBot.supportedBy($('.type-badges', main), $.RedBot.intersect(options.platforms, button.platforms)); } else { //$(this).attr('class', ''); $('.type-badges', main).empty(); } }) .appendTo(main); $('<div class="type-badges" style="margin-left:5px;display:inline-block;"></div>').appendTo(main); selectButtonType.append($('<option value="">Select button type</option>')); $.RedBot.buttonTypes.forEach(function(button) { if (options.types.indexOf(button.type) !== -1 && $.RedBot.platforms(options.platforms, button.platforms)) { selectButtonType.append($('<option value="' + button.type + '">' + button.label + '</option>')); } }); var panelUrl = $('<div class="panel panel-url" style="display:none;"/>').appendTo(container); $('<div/>').css('marginTop','5px') .append($('<input style="width:100%" class="node-input-rule-type" type="text" name="label" placeholder="Button label"/>')) .appendTo(panelUrl); $('<div/>').css('marginTop','5px') .append($('<input style="width:100%" class="node-input-rule-type" type="text" name="url" placeholder="Button URL"/>')) .appendTo(panelUrl); $('<div/>').css('marginTop','5px') .RB_hasPlatform('telegram', options.platforms) .append('<input class="node-input-rule-type" type="text" name="answer" style="width:60%" placeholder="Button feedback"/>') .append('<div class="redbot-platforms telegram"/>') .append('<input type="checkbox" name="alert" value="on" style="width:auto;margin:0px 10px 5px 10px;"/>') .append('<span>With popup</span>') .append('<div class="redbot-platforms telegram"/>') .appendTo(panelUrl); $('<div/>').css('marginTop','5px') .RB_hasPlatform('facebook', options.platforms) .append('<select name="webview_height_ratio" style="width:60%">' + '<option value="tall">Tall</option>' + '<option value="compact">Compact</option>' + '<option value="full">Full</option>' + '</select>') .append('<div class="redbot-platforms facebook"/>') .append('<input type="checkbox" name="messenger_extensions" value="on" style="width: auto;margin:0px 10px 5px 10px;"/>') .append('<span>Extensions</span><div class="redbot-platforms facebook"/>') .appendTo(panelUrl); $(panelUrl).RB_Platforms(); var panelEmail = $('<div class="panel panel-email" style="display:none;"/>').appendTo(container); $('<div/>').css('marginTop','5px') .append($('<div class="redbot-form-hint">Send user email associated to the Facebook Messenger account</div>')) .appendTo(panelEmail); var panelPhone = $('<div class="panel panel-phone" style="display:none;"/>').appendTo(container); $('<div/>').css('marginTop','5px') .append($('<div class="redbot-form-hint">Send user phone number associated to the Facebook Messenger account</div>')) .appendTo(panelPhone); var panelPostback = $('<div class="panel panel-postback" style="display:none;"/>').appendTo(container); $('<div/>').css('marginTop','5px') .append($('<input style="width:100%" class="node-input-rule-type" type="text" name="label" placeholder="Button label"/>')) .appendTo(panelPostback); $('<div/>').css('marginTop','5px') .append($('<input style="width:100%" class="node-input-rule-type" type="text" name="value" placeholder="Postback value">')) .appendTo(panelPostback); var feedbackRow = $('<div/>').css('marginTop','5px') .RB_hasPlatform(['telegram', 'slack'], options.platforms) .append('<input class="node-input-rule-type" type="text" name="answer" style="width:60%;"placeholder="Button feedback (optional)"/>') .append('<div class="redbot-platforms telegram slack"/>'); $('<input type="checkbox" name="alert" value="on" style="width: auto;margin:0px 10px 5px 10px;"/>') .RB_hasPlatform(['telegram'], options.platforms) .appendTo(feedbackRow); $('<span>With popup</span><div class="redbot-platforms telegram"/>') .RB_hasPlatform(['telegram'], options.platforms) .appendTo(feedbackRow); feedbackRow.appendTo(panelPostback); $('<div/>').css('marginTop','5px') .RB_hasPlatform('slack', options.platforms) .append('<select name="style" style="width:70%">' + '<option value="">Select button style</option>' + '<option value="default">Default</option>' + '<option value="primary">Primary</option>' + '<option value="danger">Danger</option>' + '</select>') .append('<div class="redbot-platforms slack"/>') .appendTo(panelPostback); $(panelPostback).RB_Platforms(); var panelDialog = $('<div class="panel panel-dialog" style="display:none;"/>').appendTo(container); $('<div/>').css('marginTop','5px') .append($('<input style="width:100%" class="node-input-rule-type" type="text" name="label" placeholder="Button label"/>')) .appendTo(panelDialog); $('<div/>').css('marginTop','5px') .append($('<input style="width:100%" class="node-input-rule-type" type="text" name="value" placeholder="Dialog Id">')) .appendTo(panelDialog); $('<div/>').css('marginTop','5px') .RB_hasPlatform(['telegram', 'slack'], options.platforms) .append('<input class="node-input-rule-type" type="text" name="answer" placeholder="Button feedback (optional)"/>') .appendTo(panelDialog); $('<div/>').css('marginTop','5px') .append('<select name="style" style="width:70%">' + '<option value="">Select button style</option>' + '<option value="default">Default</option>' + '<option value="primary">Primary</option>' + '<option value="danger">Danger</option>' + '</select>') .appendTo(panelDialog); var panelQuickReply = $('<div class="panel panel-quick-reply" style="display:none;"/>').appendTo(container); $('<div/>').css('marginTop','5px') .append($('<input style="width:100%" class="node-input-rule-type" type="text" name="label" placeholder="Button label"/>')) .appendTo(panelQuickReply); $('<div/>').css('marginTop','5px') .append($('<input style="width:100%" class="node-input-rule-type" type="text" name="value" placeholder="Postback value">')) .appendTo(panelQuickReply); $('<div/>').css('marginTop','5px') .append($('<input style="width:100%" class="node-input-rule-type" type="text" name="url" placeholder="Image URL"/>')) .appendTo(panelQuickReply); var panelCall = $('<div class="panel panel-call" style="display:none;"/>').appendTo(container); $('<div/>').css('marginTop','5px') .append($('<input style="width:100%" class="node-input-rule-type" type="text" name="label" placeholder="Button label"/>')) .appendTo(panelCall); $('<div/>').css('marginTop','5px') .append($('<input style="width:100%" class="node-input-rule-type" type="text" name="number" placeholder="Phone number"/>')) .appendTo(panelCall); var panelNewline = $('<div class="panel panel-newline" style="display:none;"/>').appendTo(container); $('<div/>').css('marginTop','5px') .html('This creates a new row of buttons') .appendTo(panelNewline); var panelKeyboardButton = $('<div class="panel panel-keyboardButton" style="display:none;"/>').appendTo(container); $('<div/>').css('marginTop','5px') .append($('<input style="width:100%" class="node-input-rule-type" type="text" name="label" placeholder="Button label"/>')) .appendTo(panelKeyboardButton); $('<div class="panel panel-share" style="display:none;"/>').appendTo(container); $('<div class="panel panel-logout" style="display:none;"/>').appendTo(container); $('<div class="panel panel-location" style="display:none;"/>').appendTo(container); var panelLogin = $('<div class="panel panel-login" style="display:none;"/>').appendTo(container); $('<div/>').css('marginTop','5px') .append($('<input style="width:100%" class="node-input-rule-type" type="text" name="url" placeholder="Authentication URL callback"/>')) .appendTo(panelLogin); return container; }; $.fn.RB_mountElementDialog = function(options) { options = options || {}; options.types = options.types != null ? options.types : ['text', 'textarea', 'select']; options.platforms = options.platforms != null ? options.platforms : ['slack']; options.badges = options.badges !== false; var container = $(this); var main = $('<div/>').appendTo(container); var cx = options.badges ? $.RedBot.platformClass : function() { return ''; }; var selectElementType = $('<select name="type"/>', {style:"width:200px; margin-left: 5px; text-align: center;"}) .attr('placeholder', 'Select element type') .change(function() { var type = $(this).val(); $('.panel', container).hide(); $('.panel-' + type, container).show(); // find the right button var button = $.RedBot.buttonTypes.findButton(type); // store class only if badges should be shown if (button != null && options.badges) { $(this).attr('class', button.className); } else { $(this).attr('class', ''); } }) .appendTo(main); selectElementType.append($('<option value="">Select element type</option>')); $.RedBot.elementTypes.forEach(function(button) { if (options.types.indexOf(button.type) !== -1 && $.RedBot.platforms(options.platforms, button.platforms)) { selectElementType.append($('<option value="' + button.type + '">' + button.label + '</option>')); } }); var panelText = $('<div class="panel panel-text" style="display:none;"/>').appendTo(container); $('<div/>').css('marginTop','5px') .append($('<input style="width:100%" class="node-input-rule-type" type="text" name="label" placeholder="Label"/>')) .appendTo(panelText); $('<div/>').css('marginTop','5px') .append($('<input style="width:100%" class="node-input-rule-type" type="text" name="name" placeholder="Name"/>')) .appendTo(panelText); $('<div/>').css('marginTop','5px') .append($('<input style="width:100%" class="node-input-rule-type" type="text" name="value" placeholder="Initial value"/>')) .appendTo(panelText); $('<div/>').css('marginTop','5px') .append($('<input style="width:100%" class="node-input-rule-type" type="text" name="placeholder" placeholder="Placeholder"/>')) .appendTo(panelText); $('<div/>').css('marginTop','5px') .append($('<input style="width:100%" class="node-input-rule-type" type="text" name="hint" placeholder="Hint"/>')) .appendTo(panelText); $('<div/>').css('marginTop','5px') .append('<select name="subtype" class="' + cx('select', ['']) + '" style="width:60%">' + '<option value="">Select sub-type</option>' + '<option value="email">Email</option>' + '<option value="number">Number</option>' + '<option value="tel">Telephone</option>' + '<option value="url">URL</option>' + '</select>') .append('<input type="checkbox" name="optional" value="on" style="width: auto;margin:0px 10px 5px 10px;"/>') .append('<span>Optional</span>') .appendTo(panelText); $('<div/>').css('marginTop','5px') .append($('<input style="width:45%" class="node-input-rule-type" type="number" name="min_length" placeholder="Min Length"/>')) .append($('<input style="width:45%;margin-left: 10%" class="node-input-rule-type" type="number" name="max_length" placeholder="Max Length"/>')) .appendTo(panelText); var panelTextarea = $('<div class="panel panel-textarea" style="display:none;"/>').appendTo(container); $('<div/>').css('marginTop','5px') .append($('<input style="width:100%" class="node-input-rule-type" type="text" name="label" placeholder="Label"/>')) .appendTo(panelTextarea); $('<div/>').css('marginTop','5px') .append($('<input style="width:100%" class="node-input-rule-type" type="text" name="name" placeholder="Name"/>')) .appendTo(panelTextarea); $('<div/>').css('marginTop','5px') .append($('<input style="width:100%" class="node-input-rule-type" type="text" name="value" placeholder="Initial value"/>')) .appendTo(panelTextarea); $('<div/>').css('marginTop','5px') .append($('<input style="width:100%" class="node-input-rule-type" type="text" name="placeholder" placeholder="Placeholder"/>')) .appendTo(panelTextarea); $('<div/>').css('marginTop','5px') .append($('<input style="width:100%" class="node-input-rule-type" type="text" name="hint" placeholder="Hint"/>')) .appendTo(panelTextarea); $('<div/>').css('marginTop','5px') .append('<select name="subtype" class="' + cx('select', ['']) + '" style="width:60%">' + '<option value="">Subtype</option>' + '<option value="email">Email</option>' + '<option value="number">Number</option>' + '<option value="tel">Telephone</option>' + '<option value="url">URL</option>' + '</select>') .append('<input type="checkbox" name="optional" value="on" style="width: auto;margin:0px 10px 5px 10px;"/>') .append('<span>Optional</span>') .appendTo(panelTextarea); var panelSelect = $('<div class="panel panel-select" style="display:none;"/>').appendTo(container); $('<div/>').css('marginTop','5px') .append($('<input style="width:100%" class="node-input-rule-type" type="text" name="label" placeholder="Label"/>')) .appendTo(panelSelect); $('<div/>').css('marginTop','5px') .append($('<input style="width:100%" class="node-input-rule-type" type="text" name="name" placeholder="Name"/>')) .appendTo(panelSelect); $('<div/>').css('marginTop','5px') .append($('<input style="width:100%" class="node-input-rule-type" type="text" name="value" placeholder="Initial value"/>')) .appendTo(panelSelect); $('<div/>').css('marginTop','5px') .append($('<input style="width:100%" class="node-input-rule-type" type="text" name="placeholder" placeholder="Placeholder"/>')) .appendTo(panelSelect); $('<div/>').css('marginTop','5px') .append($('<input style="width:100%" class="node-input-rule-type" type="text" name="hint" placeholder="Hint"/>')) .appendTo(panelSelect); $('<div/>').css('marginTop','5px') .append('<div class="container-options"/>') .appendTo(panelSelect); panelSelect.find('.container-options').RB_OptionsEditor({ label: 'Combo box options'}); }; $.RedBot.registerType('chatbot-inline-buttons', { category: $.RedBot.config.name, color: '#FFCC66', defaults: { name: { value: '' }, buttons: { value: [], validate: function(buttons) { if (buttons == null) { return true; // allow no buttons } var valid = true; var idx; for(idx = 0; idx < buttons.length; idx++) { if (!$.RedBot.validate.button(buttons[idx])) { valid = false; } } return valid; } }, message: { value: '' }, trackMessage: { value: false }, outputs: { value: 1 } }, inputs: 1, outputs: 1, outputLabels: function(index) { if (index === 0) { return 'to sender node'; } else { const button = this.buttons[index - 1]; if (button.type === 'postback') { if (button.label != null && button.label !== '') { return button.label + (button.value != null && button.value !== '' ? ' (' + button.value + ')' : ''); } else if (button.value != null && button.value !== '') { return button.value; } } return 'not used'; } }, paletteLabel: 'Buttons', icon: 'chatbot-inline-button.png', label: function() { return this.name || 'Buttons'; }, oneditsave: function() { var buttons = $("#node-input-buttons-container").editableList('items'); var node = this; node.buttons = []; var idx; for(idx = 0; idx < buttons.length; idx++) { node.buttons.push($(buttons[idx]).RB_getButtonData()); } // store outputs if ($('#node-input-trackMessage').is(':checked')) { node.outputs = node.buttons.length + 2; } else { node.outputs = 1; } }, oneditprepare: function() { var node = this; $('#node-input-buttons-container') .css('min-height','300px') .css('min-width','450px') .editableList({ addButton: 'Add button', addItem: function(container, i, item) { $(container).RB_mountButtonDialog({ types: ['url', 'postback', 'call', 'login', 'newline', 'logout', 'dialog'], platforms: ['facebook', 'telegram', 'slack', 'msteams'] }); $(container).RB_setButtonData(item); }, removable: true, sortable: true }); $.RedBot.fetchPlatforms() .done(function() { var buttons = node.buttons; var idx; for (idx = 0; idx < buttons.length; idx++) { $('#node-input-buttons-container').editableList('addItem', buttons[idx]); } }); }, oneditresize: function() { var dialogForm = $('#dialog-form'); var rowName = $('.form-row-name', dialogForm); var rowMessage = $('.form-row-message', dialogForm); var rowLabel = $('.form-row-label', dialogForm); var rowHint = $('.form-row-hint', dialogForm); var rowTrack = $('.form-row-track', dialogForm); var height = dialogForm.height() - rowTrack.height() - rowName.height() - rowMessage.height() - rowLabel.height() - rowHint.height() - 30; $('#node-input-buttons-container').editableList('height', height); } }); </script> <script type="text/x-red" data-template-name="chatbot-inline-buttons"> <div class="form-row form-row-name"> <label for="node-input-name"><i class="icon-tag"></i> Name</label> <input type="text" id="node-input-name" placeholder="Name"> </div> <div class="form-row form-row-message"> <label for="node-input-message"><i class="icon-envelope"></i> Message</label> <textarea id="node-input-message" placeholder="Message" style="width:93%;height:50px;"></textarea> <div style="max-width: 460px;font-size: 12px;color: #999999;line-height: 14px;clear:both;margin-top:5px;"> Supports handlebars-like variables for chat context like {{firstName}}, {{lastName}}, etc. and emoticons (:smile:, etc.) </div> </div> <div class="form-row form-row-label" style="margin-bottom:0;"> <label><i class="fa fa-list"></i> <span>Buttons</span></label> </div> <div class="form-row node-input-rule-container-row"> <ol id="node-input-buttons-container"></ol> </div> <div class="form-row form-row-track"> <label for="node-input-trackMessage">Track</label> <input type="checkbox" value="true" id="node-input-trackMessage" style="width:auto"> <span class="redbot-form-hint"> Track answers to these buttons here (will enable an output pin for each button) </span> </div> </script> <script type="text/x-red" data-help-name="chatbot-inline-buttons"><p>This node creates a message with one or more buttons in order to get a quick reaction from the users. </p> <p>Available buttons: </p> <ul> <li><p><strong>URL</strong>: Open a URL inside the client. Button feedbacks are available for Telegram and Messenger extensions in Facebook <em>[Telegram, Facebook, Viber]</em></p> </li> <li><p><strong>Postback</strong>: Allow the user to send a predefined message, the message will no be shown in the chat history. Button feedbacks are available for Telegram and Messenger extensions in Facebook <em>[Telegram, Facebook, Smooch, Viber]</em></p> </li> <li><p><strong>Phone call</strong>: Starts a phone call on mobile. <em>[Facebook]</em></p> </li> <li><p><strong>Log In</strong>: Starts the account linking flow. <em>[Facebook]</em></p> </li> <li><p><strong>Log Out</strong>: Starts the account unlinking flow. <em>[Facebook]</em></p> </li> <li><p><strong>New row</strong>: Telegram supports buttons layout with multiple row, this element just starts a new one. <em>[Telegram, Viber]</em></p> </li> </ul> <p>Platform exceptions: </p> <ul> <li><p><strong>Telegram</strong> supports a visual feedback, visible in the client, when a <code>Postback</code> or <code>URL</code> buttons is pressed</p> </li> <li><p><strong>Facebook</strong> supports some extra parameters in the <code>URL</code> button, like the size of the web view and <a href="https://developers.facebook.com/docs/messenger-platform/webview">messenger extensions</a> and a maximum od three buttons.</p> </li> </ul> <p>The tipical use of the buttons node is with the <em>Track</em> option of a <code>Sender node</code> and <a href="https://www.notion.so/4113636f565d4ff4af08bc61a644206b">Rules node</a> to capture the aswer</p> <p><img src="https://s3.us-west-2.amazonaws.com/secure.notion-static.com/56c82cb6-1c83-41c9-8ec0-2c43c4a912c6/buttons-legacy.png?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Content-Sha256=UNSIGNED-PAYLOAD&X-Amz-Credential=AKIAT73L2G45EIPT3X45%2F20230218%2Fus-west-2%2Fs3%2Faws4_request&X-Amz-Date=20230218T124941Z&X-Amz-Expires=3600&X-Amz-Signature=c96ded70d378c3cdc5ea57d43d0132f95deb061ef78f35e3b9fa5f05294eb6f9&X-Amz-SignedHeaders=host&x-id=GetObject" alt="Track answer in the Sender node"></p> <p>In this example the <code>Buttons node</code> includes two postback buttons wiht a <em>label</em> (it’s the label of the button) and a <em>value</em> (it’s what will be sent back to the chatbot if clicked). The values can be anything but it’s a good habit to use Telegram-like commands, i.e. <code>/option1</code> and <code>/option2</code>, the reason for this is that they don’t interfere with user-generated sentences and can be easily filtered by a <a href="https://www.notion.so/4113636f565d4ff4af08bc61a644206b">Rules node</a>. The <code>Sender node</code> uses the Track option, the answer will be captured and sent to the Rules node which can capture one of the possible answers with a rule <em>“Message is command …”.</em></p> <p>The <em>“Track message”</em> option enables a more readable layout to handle user’s answers:</p> <p><img src="https://s3.us-west-2.amazonaws.com/secure.notion-static.com/3b7a7638-a5ba-4316-8203-0ae783657941/buttons-new.png?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Content-Sha256=UNSIGNED-PAYLOAD&X-Amz-Credential=AKIAT73L2G45EIPT3X45%2F20230218%2Fus-west-2%2Fs3%2Faws4_request&X-Amz-Date=20230218T124941Z&X-Amz-Expires=3600&X-Amz-Signature=f9195054be758bf754e6985bcd3fd0bc280830972f9cc34e4eb7e06490b93481&X-Amz-SignedHeaders=host&x-id=GetObject" alt="Track answer in the Buttons node"></p> <p>In that case the user’s answer will be tracked directly by the <code>Buttons node</code> through one of the outputs related the postback buttons (hover on the outputs to know the output details). The first pin of the <code>Buttons node</code> is always to be connected to a <code>Sender node</code> while the last pin is the fallback (in case the user, for example, writes something instead of clicking the buttons). </p> <p>Buttons can be created programmatically by an upstream <code>Function node</code> passing array of buttons in the message payload:</p> <pre><code class="language-javascript">msg.payload = { message: &#39;This is a message above the buttons&#39;, buttons: [ { type: &#39;url&#39;, url: &#39;http://javascript-jedi.com&#39;, label: &#39;Javascript Jedi&#39; }, { type: &#39;postback&#39;, value: &#39;MY_POSTBACK_MESSAGE&#39;, label: &#39;Click me!&#39; }, { type: &#39;share&#39; } ] }; return msg; </code></pre> <p>Available parameters for the <code>msg.payload</code></p> <table> <thead> <tr> <th>Name</th> <th>Type</th> <th>Description</th> </tr> </thead> <tbody><tr> <td>message</td> <td>string</td> <td>The message text above the buttons</td> </tr> <tr> <td>buttons</td> <td>array of [button]</td> <td>The list of inline buttons</td> </tr> <tr> <td>trackMessage</td> <td>boolean</td> <td>Track the answer message in the <code>Buttons node</code>, the answer will be redirected to one of output pins related to the buttons. Default is <code>false</code>.</td> </tr> </tbody></table> <p>The <code>[button]</code> object</p> <table> <thead> <tr> <th>Name</th> <th>Type</th> <th>Description</th> </tr> </thead> <tbody><tr> <td>type</td> <td>string</td> <td>Type of button: <em>url</em>, <em>postback</em>, <em>quick-reply</em>, <em>location</em>, <em>call</em>, <em>share</em>, <em>login</em>, <em>logout</em>, <em>newline</em></td> </tr> <tr> <td>label</td> <td>string</td> <td>Label of the button</td> </tr> <tr> <td>value</td> <td>string</td> <td>Value returned as payload in <code>postback</code> buttons</td> </tr> <tr> <td>url</td> <td>string</td> <td>Url to redirect to for <code>url</code> buttons or authentication URL for <code>login</code> buttons</td> </tr> <tr> <td>number</td> <td>string</td> <td>Phone number to call for <code>call</code> buttons</td> </tr> <tr> <td>messengerExtensions</td> <td>boolean</td> <td>Include Messenger Extensions for <code>url</code> buttons</td> </tr> <tr> <td>answer</td> <td>string</td> <td>The feedback shown on Telegram client for <code>url</code> and <code>postback</code> buttons</td> </tr> <tr> <td>alert</td> <td>boolean</td> <td>Show the feedback as alert on Telegram client for <code>url</code> and <code>postback</code> buttons</td> </tr> <tr> <td>style</td> <td>string</td> <td>Style of buttons in Slack: <em>default</em>, <em>primary</em>, <em>danger</em></td> </tr> <tr> <td>webViewHeightRatio</td> <td>string</td> <td>Aspect ratio of the webview in Facebook Messenger for <code>url buttons</code>. Valid values: <em>tall</em>, <em>compact</em>, <em>full</em></td> </tr> </tbody></table> </script> <style> .form-row-checkbox { margin-bottom: 0px; } .form-row-checkbox input[type=checkbox] { width: auto; margin-top: 0px; margin-right: 5px; } .icon-platform-telegram { display: inline-block; width: 9px; height: 9px; background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAkAAAAJCAYAAADgkQYQAAAAAXNSR0IArs4c6QAAADRJREFUGBlj1F764D8DAcACk78SJQ9jwmmdZQ/BbLgimABIMYwNU80EY+Cjh4QidJ+BPAQAUcEMK/ZfXe8AAAAASUVORK5CYII=); margin-left: 3px; margin-right: 3px; vertical-align: middle; } .icon-platform-discord { display: inline-block; width: 9px; height: 9px; background: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAkAAAAJCAYAAADgkQYQAAAAAXNSR0IArs4c6QAAADxJREFUGBljVFPT+s9AALDA5G/evApjgml1dW04H64IJIIsAdIE4zPBleNh0FkRisORfQhzNMipjMSEEwBROQx6SDYaygAAAABJRU5ErkJggg=='); margin-left: 3px; margin-right: 3px; vertical-align: middle; } .icon-platform-facebook { display: inline-block; width: 9px; height: 9px; background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAkAAAAJCAYAAADgkQYQAAAAAXNSR0IArs4c6QAAAEJJREFUGBljtIqc8Z+BAGCByR9dlg5jwmnrqJlgNlwRiAcThKuCMpjQBbDxUUxCthLZVBRFyBLIJhJlHVGKGIkJJwAbVQzJXzC/gwAAAABJRU5ErkJggg==); margin-left: 3px; margin-right: 3px; vertical-align: middle; } .icon-platform-smooch { display: inline-block; width: 9px; height: 9px; background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAkAAAAJCAYAAADgkQYQAAAAAXNSR0IArs4c6QAAAENJREFUGBljXOyx/T8DAcAEk4/Z7gFjgmlkPlwRSAYmAaNhulAULfHcAVYIopEBiiKQBLoCkBiGIpAgOqCeIkZiwgkAEPoRCUXTyWoAAAAASUVORK5CYII=); margin-left: 3px; margin-right: 3px; vertical-align: middle; } .icon-platform-slack { display: inline-block; width: 9px; height: 9px; background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAkAAAAJCAYAAADgkQYQAAAAAXNSR0IArs4c6QAAAEtJREFUGBljDNvW/Z+BAGBBll/pWYLMZQjf3gPmwxWBFMAEUVQCOUzoAtj4cJNApiBbh2wqXBHIBGQJZOtJsw7ZKnRT4dYhW4XueACZqRaCOTsvfwAAAABJRU5ErkJggg==); margin-left: 3px; margin-right: 3px; vertical-align: middle; } .icon-platform-viber { display: inline-block; width: 9px; height: 9px; background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAkAAAAJCAIAAABv85FHAAAANklEQVQImWNsKL/MgAMwQaj6Dh24EJzNhEsT5XKNFVcg1tR36DRWXCHFTIhWuCZ0fcgSDAwMAO+nENww2Up1AAAAAElFTkSuQmCC); margin-left: 3px; margin-right: 3px; vertical-align: middle; } .icon-platform-universal { display: inline-block; width: 9px; height: 9px; background: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAkAAAAJCAIAAABv85FHAAAAKUlEQVQImWP8v4MBF2CCUP/d/8OF4GwmnLroL8cI9wPceYw7GdHlMAEAfGIMv3ninmsAAAAASUVORK5CYII='); margin-left: 3px; margin-right: 3px; vertical-align: middle; } .icon-platform-twilio { display: inline-block; width: 9px; height: 9px; background: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAkAAAAJCAYAAADgkQYQAAAAAXNSR0IArs4c6QAAADNJREFUGBljfGfk9Z+BAGCByQue3Qpjwun3xt5gNiO6SSDFMEmYaiYYAx89GBVh+A6bBwDzEA1NPYkyaAAAAABJRU5ErkJggg=='); margin-left: 3px; margin-right: 3px; vertical-align: middle; } .icon-platform-alexa { display: inline-block; width: 9px; height: 9px; background: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAkAAAAJCAYAAADgkQYQAAAAAXNSR0IArs4c6QAAAEJJREFUGBljVD799z8DAcCCLH/HhAnOVTnzD86GKwIpQJZA5iO0wvVhMuAmgaSQrUNWiqII3TqYQqKsI0oRIzHhBABD+hL/gIpxvwAAAABJRU5ErkJggg=='); margin-left: 3px; margin-right: 3px; vertical-align: middle; } .platform-facebook { background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAkAAAAJCAYAAADgkQYQAAAAAXNSR0IArs4c6QAAAEJJREFUGBljtIqc8Z+BAGCByR9dlg5jwmnrqJlgNlwRiAcThKuCMpjQBbDxUUxCthLZVBRFyBLIJhJlHVGKGIkJJwAbVQzJXzC/gwAAAABJRU5ErkJggg==); background-position: right 2px top 2px; background-repeat: no-repeat; } .platform-combo-facebook { background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAkAAAAJCAYAAADgkQYQAAAAAXNSR0IArs4c6QAAAEJJREFUGBljtIqc8Z+BAGCByR9dlg5jwmnrqJlgNlwRiAcThKuCMpjQBbDxUUxCthLZVBRFyBLIJhJlHVGKGIkJJwAbVQzJXzC/gwAAAABJRU5ErkJggg==); background-position: right 12px top 2px; background-repeat: no-repeat; } .platform-telegram { background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAkAAAAJCAYAAADgkQYQAAAAAXNSR0IArs4c6QAAADRJREFUGBlj1F764D8DAcACk78SJQ9jwmmdZQ/BbLgimABIMYwNU80EY+Cjh4QidJ+BPAQAUcEMK/ZfXe8AAAAASUVORK5CYII=); background-position: right 2px top 2px; background-repeat: no-repeat; } .platform-combo-telegram { background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAkAAAAJCAYAAADgkQYQAAAAAXNSR0IArs4c6QAAADRJREFUGBlj1F764D8DAcACk78SJQ9jwmmdZQ/BbLgimABIMYwNU80EY+Cjh4QidJ+BPAQAUcEMK/ZfXe8AAAAASUVORK5CYII=); background-position: right 12px top 2px; background-repeat: no-repeat; } .platform-combo-slack { background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAkAAAAJCAYAAADgkQYQAAAAAXNSR0IArs4c6QAAAEtJREFUGBljDNvW/Z+BAGBBll/pWYLMZQjf3gPmwxWBFMAEUVQCOUzoAtj4cJNApiBbh2wqXBHIBGQJZOtJsw7ZKnRT4dYhW4XueACZqRaCOTsvfwAAAABJRU5ErkJggg==); background-position: right 12px top 2px; background-repeat: no-repeat; } .platform-smooch { background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAkAAAAJCAYAAADgkQYQAAAAAXNSR0IArs4c6QAAAENJREFUGBljXOyx/T8DAcAEk4/Z7gFjgmlkPlwRSAYmAaNhulAULfHcAVYIopEBiiKQBLoCkBiGIpAgOqCeIkZiwgkAEPoRCUXTyWoAAAAASUVORK5CYII=); background-position: right 2px top 2px; background-repeat: no-repeat; } .platform-combo-alexa { background: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAkAAAAJCAYAAADgkQYQAAAAAXNSR0IArs4c6QAAAEJJREFUGBljVD799z8DAcCCLH/HhAnOVTnzD86GKwIpQJZA5iO0wvVhMuAmgaSQrUNWiqII3TqYQqKsI0oRIzHhBABD+hL/gIpxvwAAAABJRU5ErkJggg=='); background-position: right 12px top 2px; background-repeat: no-repeat; } .platform-combo-smooch { background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAkAAAAJCAYAAADgkQYQAAAAAXNSR0IArs4c6QAAAENJREFUGBljXOyx/T8DAcAEk4/Z7gFjgmlkPlwRSAYmAaNhulAULfHcAVYIopEBiiKQBLoCkBiGIpAgOqCeIkZiwgkAEPoRCUXTyWoAAAAASUVORK5CYII=); background-position: right 12px top 2px; background-repeat: no-repeat; } .platform-telegram-facebook, .platform-facebook-telegram { background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAkAAAAJCAYAAADgkQYQAAAAAXNSR0IArs4c6QAAADRJREFUGBlj1F764D8DAcACk78SJQ9jwmmdZQ/BbLgimABIMYwNU80EY+Cjh4QidJ+BPAQAUcEMK/ZfXe8AAAAASUVORK5CYII=), url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAkAAAAJCAYAAADgkQYQAAAAAXNSR0IArs4c6QAAAEJJREFUGBljtIqc8Z+BAGCByR9dlg5jwmnrqJlgNlwRiAcThKuCMpjQBbDxUUxCthLZVBRFyBLIJhJlHVGKGIkJJwAbVQzJXzC/gwAAAABJRU5ErkJggg==); background-position: right 2px top 2px, right 12px top 2px; background-repeat: no-repeat, no-repeat; } .platform-combo-telegram-facebook, .platform-combo-facebook-telegram { background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAkAAAAJCAYAAADgkQYQAAAAAXNSR0IArs4c6QAAADRJREFUGBlj1F764D8DAcACk78SJQ9jwmmdZQ/BbLgimABIMYwNU80EY+Cjh4QidJ+BPAQAUcEMK/ZfXe8AAAAASUVORK5CYII=), url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAkAAAAJCAYAAADgkQYQAAAAAXNSR0IArs4c6QAAAEJJREFUGBljtIqc8Z+BAGCByR9dlg5jwmnrqJlgNlwRiAcThKuCMpjQBbDxUUxCthLZVBRFyBLIJhJlHVGKGIkJJwAbVQzJXzC/gwAAAABJRU5ErkJggg==); background-position: right 12px top 2px, right 22px top 2px; background-repeat: no-repeat, no-repeat; } .platform-combo-telegram-facebook-viber { background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAkAAAAJCAYAAADgkQYQAAAAAXNSR0IArs4c6QAAADRJREFUGBlj1F764D8DAcACk78SJQ9jwmmdZQ/BbLgimABIMYwNU80EY+Cjh4QidJ+BPAQAUcEMK/ZfXe8AAAAASUVORK5CYII=), url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAkAAAAJCAYAAADgkQYQAAAAAXNSR0IArs4c6QAAAEJJREFUGBljtIqc8Z+BAGCByR9dlg5jwmnrqJlgNlwRiAcThKuCMpjQBbDxUUxCthLZVBRFyBLIJhJlHVGKGIkJJwAbVQzJXzC/gwAAAABJRU5ErkJggg==), url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAkAAAAJCAIAAABv85FHAAAANklEQVQImWNsKL/MgAMwQaj6Dh24EJzNhEsT5XKNFVcg1tR36DRWXCHFTIhWuCZ0fcgSDAwMAO+nENww2Up1AAAAAElFTkSuQmCC); background-position: right 12px top 2px, right 22px top 2px, right 32px top 2px; background-repeat: no-repeat, no-repeat; } .platform-telegram-slack, platform-slack-telegram { background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAkAAAAJCAYAAADgkQYQAAAAAXNSR0IArs4c6QAAADRJREFUGBlj1F764D8DAcACk78SJQ9jwmmdZQ/BbLgimABIMYwNU80EY+Cjh4QidJ+BPAQAUcEMK/ZfXe8AAAAASUVORK5CYII=), url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAkAAAAJCAYAAADgkQYQAAAAAXNSR0IArs4c6QAAAEtJREFUGBljDNvW/Z+BAGBBll/pWYLMZQjf3gPmwxWBFMAEUVQCOUzoAtj4cJNApiBbh2wqXBHIBGQJZOtJsw7ZKnRT4dYhW4XueACZqRaCOTsvfwAAAABJRU5ErkJggg==); background-position: right 2px top 2px, right 12px top 2px; background-repeat: no-repeat, no-repeat; } .platform-telegram-slack-viber { background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAkAAAAJCAYAAADgkQYQAAAAAXNSR0IArs4c6QAAADRJREFUGBlj1F764D8DAcACk78SJQ9jwmmdZQ/BbLgimABIMYwNU80EY+Cjh4QidJ+BPAQAUcEMK/ZfXe8AAAAASUVORK5CYII=), url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAkAAAAJCAYAAADgkQYQAAAAAXNSR0IArs4c6QAAAEtJREFUGBljDNvW/Z+BAGBBll/pWYLMZQjf3gPmwxWBFMAEUVQCOUzoAtj4cJNApiBbh2wqXBHIBGQJZOtJsw7ZKnRT4dYhW4XueACZqRaCOTsvfwAAAABJRU5ErkJggg==), url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAkAAAAJCAIAAABv85FHAAAANklEQVQImWNsKL/MgAMwQaj6Dh24EJzNhEsT5XKNFVcg1tR36DRWXCHFTIhWuCZ0fcgSDAwMAO+nENww2Up1AAAAAElFTkSuQmCC); background-position: right 2px top 2px, right 12px top 2px, right 22px top 2px; background-repeat: no-repeat, no-repeat; } .platform-combo-telegram-slack { background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAkAAAAJCAYAAADgkQYQAAAAAXNSR0IArs4c6QAAADRJREFUGBlj1F764D8DAcACk78SJQ9jwmmdZQ/BbLgimABIMYwNU80EY+Cjh4QidJ+BPAQAUcEMK/ZfXe8AAAAASUVORK5CYII=), url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAkAAAAJCAYAAADgkQYQAAAAAXNSR0IArs4c6QAAAEtJREFUGBljDNvW/Z+BAGBBll/pWYLMZQjf3gPmwxWBFMAEUVQCOUzoAtj4cJNApiBbh2wqXBHIBGQJZOtJsw7ZKnRT4dYhW4XueACZqRaCOTsvfwAAAABJRU5ErkJggg==); background-position: right 12px top 2px, right 22px top 2px; background-repeat: no-repeat, no-repeat; } .platform-combo-telegram-viber { background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAkAAAAJCAYAAADgkQYQAAAAAXNSR0IArs4c6QAAADRJREFUGBlj1F764D8DAcACk78SJQ9jwmmdZQ/BbLgimABIMYwNU80EY+Cjh4QidJ+BPAQAUcEMK/ZfXe8AAAAASUVORK5CYII=), url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAkAAAAJCAIAAABv85FHAAAANklEQVQImWNsKL/MgAMwQaj6Dh24EJzNhEsT5XKNFVcg1tR36DRWXCHFTIhWuCZ0fcgSDAwMAO+nENww2Up1AAAAAElFTkSuQmCC); background-position: right 12px top 2px, right 22px top 2px; background-repeat: no-repeat, no-repeat; } .platform-smooch-facebook, .platform-facebook-smooch { background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAkAAAAJCAYAAADgkQYQAAAAAXNSR0IArs4c6QAAAENJREFUGBljXOyx/T8DAcAEk4/Z7gFjgmlkPlwRSAYmAaNhulAULfHcAVYIopEBiiKQBLoCkBiGIpAgOqCeIkZiwgkAEPoRCUXTyWoAAAAASUVORK5CYII=), url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAkAAAAJCAYAAADgkQYQAAAAAXNSR0IArs4c6QAAAEJJREFUGBljtIqc8Z+BAGCByR9dlg5jwmnrqJlgNlwRiAcThKuCMpjQBbDxUUxCthLZVBRFyBLIJhJlH