UNPKG

line-simulator

Version:

LINE Simulator for Bot developer

1,369 lines (1,291 loc) 50.9 kB
(function () { // Load settings at startup function loadSettings() { userId = localStorage.getItem('userId'); let channelSecret = localStorage.getItem('channelSecret'); let channelToken = localStorage.getItem('channelToken'); let botAPIAddress = localStorage.getItem('botAPIAddress'); $("#userId")[0].value = userId; $("#channelSecret")[0].value = channelSecret; $("#channelToken")[0].value = channelToken; $("#botAPIAddress")[0].value = botAPIAddress; if (!userId || !channelToken || !channelToken || !botAPIAddress) { // Do nothing. Let settings pane open. } else { setSettings(); } } // Add chat item when events are received from Bot API. function receiveMessages(data) { for (i = 0; i < data.messages.length; i++) { // Create list item from recevied message. var li = parseDataAndReturnListItem(data.messages[i]); // append the reply. appendBotReplyToThread(li); } } // Handle key down event for textarea. function sendByEnter(e) { let code = (e.keyCode ? e.keyCode : e.which); if (code == 13) { //Enter keycode sendFromChatBox(); } } // Handle key down event for bot textarea function sendByEnterFromBot(e) { let code = (e.keyCode ? e.keyCode : e.which); if (code == 13) { //Enter keycode sendTextFromBot(); } } // Copy JSON text only. function selectRaw(e) { let code = (e.keyCode ? e.keyCode : e.which); if (e.ctrlKey && code == 65) { //CTRL+A let selection = window.getSelection(); let range = document.createRange(); range.selectNodeContents($('#rawdata')[0]); selection.removeAllRanges(); selection.addRange(range); } } // Disable Ctrl+A so that it only works in JSON raw. function disableCtrlA(e) { let code = (e.keyCode ? e.keyCode : e.which); if (e.ctrlKey && code == 65) { //CTRL+A return false; } } // Update time function updateTime() { var current = new Date(); $('.time').each(function (index, value) { this.innerText = current.getHours() + ":" + current.getMinutes(); }); } // Craete sockect for bi-directional real-time communication. var socket = io(); socket.on('reply', function (data) { receiveMessages(data); }); // Handle binding function bindHandlers() { $('#message-to-send').bind("keypress", {}, sendByEnter); $('#message-from-bot').bind("keypress", {}, sendByEnterFromBot); $('.chat-raw').bind("keydown", {}, selectRaw); $(document).bind("keydown", {}, disableCtrlA); $('#confirm-title').on("input", () => { syncPreviewValue('confirm-title', false); }); $('#confirm-yes').on("input", () => { syncPreviewValue('confirm-yes', false); }); $('#confirm-no').on("input", () => { syncPreviewValue('confirm-no', false); }); $('#buttons-image').on("change", () => { syncPreviewImage('buttons-image'); }); $('#buttons-title').on("input", () => { syncPreviewValue('buttons-title', true); }); $('#buttons-text').on("input", () => { syncPreviewValue('buttons-text', false); }); $('#buttons-action-1').on("input", () => { syncPreviewValue('buttons-action-1', true); }); $('#buttons-action-2').on("input", () => { syncPreviewValue('buttons-action-2', true); }); $('#buttons-action-3').on("input", () => { syncPreviewValue('buttons-action-3', true); }); $('#buttons-action-4').on("input", () => { syncPreviewValue('buttons-action-4', true); }); $('#loadJsonFile').on("change", () => { loadJson(); }); // Tab menu $('.nav-tabs a').click(function (e) { e.preventDefault() $(this).tab('show') }) // dropdown menu $('.dropdown a').click(function (e) { $(this).parents('div:first').children('.btn').text($(this).text()); }) } // Update time every minutes, setInterval(updateTime, 60000); loadSettings(); // Setup key pressdown event. bindHandlers(); }()); //#region settings var userId = ""; function setSettings() { pocMode = false; let userIdInput = $("#userId")[0]; let channelSecretInput = $('#channelSecret')[0]; let channelTokenInput = $('#channelToken')[0]; let botAPIAddressInput = $('#botAPIAddress')[0]; if (!userIdInput.value || !channelSecretInput.value || !channelTokenInput.value || !botAPIAddressInput.value) { $('.warning')[0].innerText = "Please set values"; } else { userId = userIdInput.value; channelSecret = channelSecretInput.value; channelToken = channelTokenInput.value; botAPIAddress = botAPIAddressInput.value; localStorage.setItem("userId", userId); localStorage.setItem("channelSecret", channelSecret); localStorage.setItem("channelToken", channelToken); localStorage.setItem("botAPIAddress", botAPIAddress); $.ajax({ url: "/channelSettings", type: "POST", data: { "botAPIAddress": botAPIAddress, "channelSecret": channelSecret, "channelToken": channelToken, "userId": userId }, success: function (data) { $('.warning')[0].innerText = ""; setPocMode(false); }, error: function (xhr, ajaxOptions, thrownError) { $('.warning')[0].innerText = `Error : ${JSON.parse(xhr.responseText).message}`; } }); } } var pocMode; function setPocMode(mode) { pocMode = mode; if (pocMode && $('.bot-chat').hasClass('hide')) { $('.bot-chat').removeClass('hide'); } else if (!pocMode && !$('.bot-chat').hasClass('hide')) { $('.bot-chat').addClass('hide'); } $.ajax({ url: "/pocMode", type: "POST", data: { "pocMode": pocMode }, success: function (data) { $('.warning')[0].innerText = ""; toggleSettings(); } }); } //#endregion // Handle Chat Item select event. function onSelectChatItem(obj) { if (pocMode) { $('.chat-item-tool').remove(); $(obj).after(`<li tabindex="1" class="chat-item-tool active-li"> <div> <i class="fa fa-trash-o fa-inverse fa-2x" onclick="removeChatItem(this);"></i> <i class="fa fa-arrow-up fa-inverse fa-2x" onclick="moveItem(this, true)"></i> <i class="fa fa-arrow-down fa-inverse fa-2x" onclick="moveItem(this, false)"></i> <i class="fa fa-times fa-inverse fa-2x right" onclick="{$('.chat-item-tool').remove();}"></i> </div> </li>`); if (obj.hasClass('chat-user')) { $('.chat-item-tool').addClass('chat-user'); } $('.chat-item-tool')[0].focus(); } // Display RowData else { $('.chat-raw').children('pre')[0].innerText = JSON.stringify( JSON.parse($(obj).attr('data')), null, '\t'); if ($('.chat-raw').hasClass("hide")) { $('.chat-raw').removeClass("hide"); } } } function moveItem(obj, up) { let target; if (up) { target = $(obj).parents('li').prev().prev() $(obj).parents('li').prev().insertBefore(target); $(obj).parents('li').insertBefore(target); } else { target = $(obj).parents('li').next(); origin = $(obj).parents('li').prev(); origin.insertAfter(target); $(obj).parents('li').insertAfter(origin); } } function removeChatItem(obj) { $(obj).parents('li').prev().remove(); $(obj).parents('li').remove(); } //#region append chat item // Parse LINE message object into HTML list item. // tabindex attribute is neccesary to set focus on it for auto scroll to bottom. function parseDataAndReturnListItem(data) { if (data.type == "text") { var reply = `<li tabindex="1" data='${JSON.stringify(data)}' class="chat-bot chat-text" onclick='onSelectChatItem($(this))'>${data.text}</li>`; } else if (data.type == "sticker") { var reply = `<li tabindex="1" data='${JSON.stringify(data)}' class="chat-bot chat-sticker" onclick='onSelectChatItem($(this))'>stickerId:<br/>${data.stickerId}</li>`; } else if (data.type == "image") { var reply = `<li tabindex="1" data='${JSON.stringify(data)}' class="chat-bot chat-img" onclick='onSelectChatItem($(this))'><img src="${data.previewImageUrl}"/></li>`; } else if (data.type == "location") { var reply = `<li tabindex="1" data='${JSON.stringify(data)}' class="chat-bot chat-location" onclick='onSelectChatItem($(this))'> <div> <i class="fa fa-flag"></i> </div> <div> ${data.title} <br/> ${data.address} </div> </li>`; } else if (data.type == "video") { var reply = `<li tabindex="1" data='${JSON.stringify(data)}' class="chat-bot chat-img" onclick='onSelectChatItem($(this))'> <video controls autoplay> <source src="${data.originalContentUrl}" type="video/mp4> </video> </li>` } else if (data.type == "audio") { let audioId = Date.now(); let audioLength = data.duration; let minutes = Math.floor(audioLength / 60000); let seconds = ((audioLength % 60000) / 1000).toFixed(0); var reply = `<li tabindex="1" data='${JSON.stringify(data)}' class="chat-bot chat-audio" onclick='onSelectChatItem($(this))'> <i class="fa fa-play-circle fa-lg" onclick="play('#${audioId}');"></i> ${minutes + ":" + (seconds < 10 ? '0' : '') + seconds}  ----------- <audio id="${audioId}"> <source src="${data.originalContentUrl}"> </audio> </li>` } else if (data.type == "template") { if (data.template.type == "buttons") { var reply = `<li tabindex="1" data='${JSON.stringify(data)}' class="chat-bot chat-template chat-template-buttons" onclick='onSelectChatItem($(this))'>`; if (data.template.thumbnailImageUrl) { if (data.template.thumbnailImageUrl.indexOf('url') > -1) { reply += `<div class="chat-template-buttons-image" style='background-image:${data.template.thumbnailImageUrl}'></div>`; } else { reply += `<div class="chat-template-buttons-image" style="background-image:url(${data.template.thumbnailImageUrl})"></div>`; } } if (data.template.title) { reply += `<div class="chat-template-buttons-title">${data.template.title}</div>`; } reply += `<div class="chat-template-buttons-text">${data.template.text}</div>`; for (let i = 0; i < data.template.actions.length; i++) { let action = data.template.actions[i]; if (action.type == "postback") { if (action.text) { reply += `<div class="chat-template-buttons-button" onclick="{sendPostback('${action.data}');sendTextMessage('${action.text}');}">${action.label}</div>`; } else { reply += `<div class="chat-template-buttons-button" onclick="{sendTextMessage('${action.data}');}">${action.label}</div>`; } } else if (action.type == "message") { reply += `<div class="chat-template-buttons-button" onclick="{sendTextMessage('${action.text}');}">${action.label}</div>`; } else if (action.type == "uri") { reply += `<div class="chat-template-buttons-button"><a href="${action.uri}" target="_blank">${action.label}</a></div>`; } } reply += '</li>'; } else if (data.template.type == "confirm") { var reply = `<li tabindex="1" data='${JSON.stringify(data)}' class="chat-bot chat-template chat-template-confirm" onclick='onSelectChatItem($(this))'> <div class="chat-template-confirm-text">${data.template.text}</div> <div class="chat-template-confirm-yes" onclick="{sendTextMessage('${data.template.actions[0].text}');}">${data.template.actions[0].label}</div> <div class="chat-template-confirm-no" onclick="{sendTextMessage('${data.template.actions[1].text}');}">${data.template.actions[1].label}</div> </li>`; } else if (data.template.type == "carousel") { var reply = `<li class="chat-bot chat-icon-only"></li> <li tabindex="1" data='${JSON.stringify(data)}' class="chat-template-carousel" onclick='onSelectChatItem($(this))'>`; for (let i = 0; i < data.template.columns.length; i++) { let column = data.template.columns[i]; reply += `<div class="chat-template-buttons">`; if (column.thumbnailImageUrl) { if (column.thumbnailImageUrl.indexOf('url') > -1) { reply += `<div class="chat-template-buttons-image" style='background-image:${column.thumbnailImageUrl}'></div>`; } else { reply += `<div class="chat-template-buttons-image" style="background-image:url(${column.thumbnailImageUrl})"></div>`; } } if (column.title) { reply += `<div class="chat-template-buttons-title">${column.title}</div>`; } reply += `<div class="chat-template-buttons-text">${column.text}</div>`; for (let j = 0; j < column.actions.length; j++) { let action = column.actions[j]; if (action.type == "postback") { if (action.text) { reply += `<div class="chat-template-buttons-button" onclick="{sendPostback('${action.data}');sendTextMessage('${action.text}');}">${action.label}</div>`; } else { reply += `<div class="chat-template-buttons-button" onclick="{sendTextMessage('${action.data}');}">${action.label}</div>`; } } else if (action.type == "message") { reply += `<div class="chat-template-buttons-button" onclick="{sendTextMessage('${action.text}');}">${action.text}</div>`; } else if (action.type == "uri") { reply += `<div class="chat-template-buttons-button"><a href="${action.uri}" target="_blank">${action.label}</a></div>`; } } reply += `</div>`; } reply += `</li>`; } else if (data.template.type == "image_carousel") { var reply = `<li class="chat-bot chat-icon-only"></li> <li tabindex="1" data='${JSON.stringify(data)}' class="chat-template-carousel" onclick='onSelectChatItem($(this))'>`; for (let i = 0; i < data.template.columns.length; i++) { let column = data.template.columns[i]; reply += `<div class="chat-template-image-carousel">`; if (column.imageUrl) { if (column.imageUrl.indexOf('url') > -1) { reply += `<div class="chat-template-image-carousel-image" style='background-image:${column.imageUrl}'></div>`; } else { reply += `<div class="chat-template-image-carousel-image" style="background-image:url(${column.imageUrl})"></div>`; } } reply += '<div class="chat-template-image-carousel-button">'; let action = column.action; if (action.type == "postback") { if (action.text) { reply += `<div class="chat-template-image-carousel-button-content" onclick="{sendPostback('${action.data}');sendTextMessage('${action.text}');}">${action.label}</div>`; } else { reply += `<div class="chat-template-image-carousel-button-content" onclick="{sendTextMessage('${action.data}');}">${action.label}</div>`; } } else if (action.type == "message") { reply += `<div class="chat-template-image-carousel-button-content" onclick="{sendTextMessage('${action.text}');}">${action.text}</div>`; } else if (action.type == "uri") { reply += `<div class="chat-template-image-carousel-button-content"><a href="${action.uri}" target="_blank">${action.label}</a></div>`; } reply += `</div></div>`; } reply += `</li>`; } } else if (data.type == "imagemap") { let imagemapId = Date.now(); var reply = `<li tabindex="1" data='${JSON.stringify(data)}' class="chat-imagemap" onclick='onSelectChatItem($(this))'> <img src="${data.baseUrl}/1040.png" alt="${data.altText}" usemap="#${imagemapId}"/><map name="${imagemapId}">`; for (let i = 0; i < data.actions.length; i++) { let action = data.actions[i]; if (action.type === "uri") { reply += `<area shape="rect" coords="${action.area.x},${action.area.y},${action.area.width + action.area.x},${action.area.height}" href="${action.linkUri}" target="_blank">`; } else if (action.type === "message") { reply += `<area shape="rect" coords="${action.area.x},${action.area.y},${action.area.width + action.area.x},${action.area.height}" href="javascript:sendTextMessage('${action.text}');">`; } } reply += `</map></li>`; } return reply; } // Append user input item to chat body function appendUserInputToThread(sendObject, path) { let chatThread = $(".chat-thread ul"); let message = sendObject.message; if (message.type === "text") { chatThread.append(`<li tabindex="1" data='${JSON.stringify(sendObject)}' class="chat-user chat-text" onclick='onSelectChatItem($(this))'> ${message.text}</li>`); } else if (message.type === "image") { } else if (message.type === "location") { chatThread.append(`<li tabindex="1" data='${JSON.stringify(sendObject)}' class="chat-user chat-location" onclick='onSelectChatItem($(this))'> <div><i class="fa fa-flag"></i></div> <div>${message.title}<br/>${message.address}</div></li>`); } else if (message.type === "sticker") { chatThread.append(`<li tabindex="1" data='${JSON.stringify(sendObject)}' class="chat-user chat-sticker" onclick='onSelectChatItem($(this))'> stickerId:<br/>${message.stickerId}</li>`); } $('.chat-thread li').last().addClass('active-li').focus(); $('#message-to-send')[0].focus(); } // Append image message as user. function appendImageToThread(path, sendObject) { let chatThread = $(".chat-thread ul"); chatThread.append(`<li tabindex="1" data='${JSON.stringify(sendObject)}' class="chat-user chat-img" onclick='onSelectChatItem($(this))'> <img alt="Embedded Image" src="${path}"/> </li>`); $('.chat-thread li').last().addClass('active-li').focus(); $('#message-to-send')[0].focus(); } // Append video message as user. function appendVideoToThread(path, sendObject) { let chatThread = $(".chat-thread ul"); chatThread.append(`<li tabindex="1" data='${JSON.stringify(sendObject)}' class="chat-user chat-img" onclick='onSelectChatItem($(this))'> <video controls autoplay> <source src="${path}" type="video/mp4"> </video> </li>`); $('.chat-thread li').last().addClass('active-li').focus(); $('#message-to-send')[0].focus(); } // Play audio for chat-audio function play(element) { $(element)[0].play(); } // Append Audio message as user. function appendAudioToThread(path, sendObject) { let chatThread = $(".chat-thread ul"); let audioId = Date.now(); chatThread.append(`<li tabindex="1" data='${JSON.stringify(sendObject)}' class="chat-user chat-audio" onclick='onSelectChatItem($(this))'> <i class="fa fa-play-circle fa-lg" onclick="play('#${audioId}');"></i> 11:11  ----------- <audio id="${audioId}" src="${path}"><audio> </li>`); $('.chat-thread li').last().addClass('active-li').focus(); $('#message-to-send')[0].focus(); } // display user media input to thread. function appendMediaToThread(data) { let fileext = data.filePath.split('.')[1]; if (fileext === "mp4") { appendVideoToThread(data.filePath, data.sendObject); } else if (fileext === "png" || fileext === "jpeg" || fileext === "jpg") { appendImageToThread(data.filePath, data.sendObject); } else if (fileext === "m4a") { appendAudioToThread(data.filePath, data.sendObject); } else { return; } } // Append bot input item to chat body function appendBotReplyToThread(data) { let chatThread = $(".chat-thread ul"); chatThread.append(data); $('.chat-thread li').last().addClass('active-li').focus(); $('#message-to-send')[0].focus(); } //#endregion //#region Send data to local API // upload file. !!!Need file types. function uploadFile() { var filename = $("#filename")[0].value; // Read file data var reader = new FileReader(); // Callback when file read. reader.onload = function (event) { $("#filename")[0].value = ""; let result = event.target.result; var sendObject = { "filename": filename, "userId": userId, "base64string": result }; $.ajax({ url: "/upload", type: "POST", data: sendObject, success: function (data) { appendMediaToThread(data); } }); }; reader.readAsDataURL($("#filename")[0].files[0]); } // Send text from text area. function sendFromChatBox() { var text = $('#message-to-send')[0].value; // Reset input $('#message-to-send')[0].value = ""; sendTextMessage(text); } // send data to Bot API. function send(sendObject) { // if POC mode, then do not send to bot. if (pocMode) { return; } $.ajax({ url: "/send", contentType: "application/json", type: "POST", data: JSON.stringify({ "events": [sendObject] }), success: function () { }, error: function (xhr, ajaxOptions, thrownError) { } }); } // Send text message. function sendTextMessage(text) { // Craft LINE message var sendObject = { "replyToken": "dummyToken", "type": "message", "timestamp": 1462629479859, "source": { "type": "user", "userId": userId }, "message": { "id": "325708", "type": "text", "text": text } }; appendUserInputToThread(sendObject); send(sendObject); } // Send postback event. function sendPostback(postback, params) { // Craft LINE message var sendObject = { "replyToken": "dummyToken", "type": "postback", "timestamp": 1462629479859, "source": { "type": "user", "userId": userId }, "postback": { "data": postback, "params": params } }; send(sendObject); } // Send sticker event. function sendSticker() { // Craft LINE message var sendObject = { "replyToken": "nHuyWiB7yP5Zw52FIkcQobQuGDXCTA", "type": "message", "timestamp": 1462629479859, "source": { "type": "user", "userId": userId }, "message": { "id": "325708", "type": "sticker", "packageId": $('#packageId')[0].value, "stickerId": $('#stickerId')[0].value } }; appendUserInputToThread(sendObject); send(sendObject); } // Send Location event. function sendAddress() { // Craft LINE message var sendObject = { "replyToken": "nHuyWiB7yP5Zw52FIkcQobQuGDXCTA", "type": "message", "timestamp": 1462629479859, "source": { "type": "user", "userId": userId }, "message": { "id": "325708", "type": "location", "title": $('#title')[0].value, "address": $('#address')[0].value, "latitude": $('#latitude')[0].value, "longitude": $('#longitude')[0].value } }; appendUserInputToThread(sendObject); send(sendObject); } /* System messages */ function sendFollow() { // Craft LINE message var sendObject = { "replyToken": "nHuyWiB7yP5Zw52FIkcQobQuGDXCTA", "type": "follow", "timestamp": 1462629479859, "source": { "type": "user", "userId": userId } }; send(sendObject); } function sendUnfollow() { // Craft LINE message var sendObject = { "type": "unfollow", "timestamp": 1462629479859, "source": { "type": "user", "userId": userId } } send(sendObject); } function sendJoin() { // Craft LINE message var sendObject = { "replyToken": "nHuyWiB7yP5Zw52FIkcQobQuGDXCTA", "type": "join", "timestamp": 1462629479859, "source": { "type": "group", "groupId": "C4af4980629..." } } send(sendObject); } function sendLeave() { // Craft LINE message var sendObject = { "type": "leave", "timestamp": 1462629479859, "source": { "type": "group", "groupId": "C4af4980629..." } } send(sendObject); } function sendBeacon() { // Craft LINE message var sendObject = { "replyToken": "nHuyWiB7yP5Zw52FIkcQobQuGDXCTA", "type": "beacon", "timestamp": 1462629479859, "source": { "type": "user", "userId": userId }, "beacon": { "hwid": $('#hwid')[0].value, "type": $('#type')[0].value } } send(sendObject); } //#endregion //#region Send data as Bot (POC features) // Send text as bot function sendTextFromBot() { let inputMessage = $('#message-from-bot')[0].value; // Reset input $('#message-from-bot')[0].value = ""; let data = { "type": "text", "text": inputMessage } let li = parseDataAndReturnListItem(data); // append the reply. appendBotReplyToThread(li); } // Send image as bot function uploadFileFromBot(message) { // if it contains fakepath, then get actual data and send it to server. let reader = new FileReader(); reader.onload = function (event) { let filename = $("#filename-from-bot")[0].value; let fileext = filename.split('.')[1]; let type = "file"; let data = {}; $("#filename-from-bot")[0].value = ""; if (fileext === "mp4") { type = "video"; } else if (fileext === "png" || fileext === "jpeg" || fileext === "jpg") { type = "image"; } else if (fileext === "m4a") { type = "audio" } let filedata = event.target.result; // Craft LINE message if (type === "video") { data = { "type": "video", "originalContentUrl": filedata, "previewImageUrl": filedata } } else if (type === "image") { data = { "type": "image", "originalContentUrl": filedata, "previewImageUrl": filedata } } else if (type === "audio") { data = { "type": "audio", "originalContentUrl": filedata, "duration": 0 } } let li = parseDataAndReturnListItem(data); // append the reply. appendBotReplyToThread(li); }; reader.readAsDataURL($("#filename-from-bot")[0].files[0]); } function sendStickerFromBot() { // Craft LINE message let data = { "type": "sticker", "packageId": $('#packageId-from-bot')[0].value, "stickerId": $('#stickerId-from-bot')[0].value }; let li = parseDataAndReturnListItem(data); appendBotReplyToThread(li); } function sendAddressFromBot() { // Craft LINE message let data = { "type": "location", "title": $('#title-from-bot')[0].value, "address": $('#address-from-bot')[0].value, "latitude": $('#latitude-from-bot')[0].value, "longitude": $('#longitude-from-bot')[0].value }; let li = parseDataAndReturnListItem(data); appendBotReplyToThread(li); } function sendConfirmFromBot() { var data = { "type": "template", "altText": "this is a confirm template", "template": { "type": "confirm", "text": $('#confirm-title')[0].value, "actions": [ { "type": "message", "label": $('#confirm-yes')[0].value, "text": $('#confirm-yes')[0].value }, { "type": "message", "label": $('#confirm-no')[0].value, "text": $('#confirm-no')[0].value } ] } } let li = parseDataAndReturnListItem(data); appendBotReplyToThread(li); } // Send Buttons function syncPreviewValue(elementName, hideWithoutValue) { let previewElem = $(`#preview-${elementName}`); let originalElem = $(`#${elementName}`); if (hideWithoutValue) { if (originalElem[0].value === "" && !previewElem.hasClass("hide")) { previewElem.addClass("hide"); } else if (originalElem[0].value !== "" && previewElem.hasClass("hide")) { previewElem.removeClass("hide"); } } previewElem[0].innerText = originalElem[0].value; } function syncPreviewImage(elementName) { var reader = new FileReader(); reader.onload = function (event) { let previewElem = $(`#preview-${elementName}`); if (previewElem.hasClass("hide")) { previewElem.removeClass("hide"); } // Render thumbnail. event.target.result; previewElem.css("background-image", `url(${event.target.result})`); }; // Read in the image file as a data URL. reader.readAsDataURL($(`#${elementName}`)[0].files[0]); } function removePreviewImage(elementName) { $(`#${elementName}`).val(''); let previewElement = $(`#preview-${elementName}`); previewElement.css("background-image", ``); previewElement.addClass('hide'); } function sendButtonsFromBot() { var data = { "type": "template", "altText": "this is a buttons template", "template": { "type": "buttons", "imageAspectRatio": "rectangle", "imageSize": "cover", "imageBackgroundColor": "#FFFFFF", "title": $('#buttons-title')[0].value, "text": $('#buttons-text')[0].value, "actions": [ ] } } for (let i = 0; i < $('.buttons-actions').length; i++) { let actionElement = $('.buttons-actions')[i]; if ($('input', actionElement)[0].value !== "") { let type = $('button', actionElement)[0].innerText; if (type === "message") { data.template.actions.push({ "type": type, "label": $('input', actionElement)[0].value, "text": $('input', actionElement)[1].value }) } else if (type === "postback") { data.template.actions.push({ "type": type, "label": $('input', actionElement)[0].value, "text": $('input', actionElement)[0].value, "data": $('input', actionElement)[1].value }) } else if (type === "uri") { data.template.actions.push({ "type": type, "label": $('input', actionElement)[0].value, "uri": $('input', actionElement)[1].value }) } } } if ($('#preview-buttons-image')[0].style['background-image'] !== "") { data.template.thumbnailImageUrl = $('#preview-buttons-image')[0].style['background-image']; } let li = parseDataAndReturnListItem(data); appendBotReplyToThread(li); } // Carousel var colNum = 0; function removeCarouselPreviewImage(elementName) { $(`#${elementName}`).val(''); let previewElement = $(`#preview-${elementName}-${colNum}`); previewElement.css("background-image", ``); previewElement.addClass('hide'); } function addColumn() { colNum = $('#preview-chat-template-carousel')[0].children.length; $('#preview-chat-template-carousel').append( `<div class="chat-template-buttons" onclick="selectColumn(${colNum});"> <div class="chat-template-buttons-image hide" id="preview-carousel-image-${colNum}"></div> <div class="chat-template-buttons-title hide" id="preview-carousel-title-${colNum}"></div> <div class="chat-template-buttons-text" id="preview-carousel-text-${colNum}"></div> <div class="chat-template-buttons-button" id="preview-carousel-action-1-${colNum}"></div> <div class="chat-template-buttons-button hide" id="preview-carousel-action-1-data-${colNum}"></div> <div class="chat-template-buttons-button hide" id="preview-carousel-action-1-type-${colNum}">message</div> <div class="chat-template-buttons-button hide" id="preview-carousel-action-2-${colNum}"></div> <div class="chat-template-buttons-button hide" id="preview-carousel-action-2-data-${colNum}"></div> <div class="chat-template-buttons-button hide" id="preview-carousel-action-2-type-${colNum}">message</div> <div class="chat-template-buttons-button hide" id="preview-carousel-action-3-${colNum}"></div> <div class="chat-template-buttons-button hide" id="preview-carousel-action-3-data-${colNum}"></div> <div class="chat-template-buttons-button hide" id="preview-carousel-action-3-type-${colNum}">message</div> </div>` ); selectColumn(colNum); } function removeColumn() { $('#preview-chat-template-carousel')[0].children[colNum].remove(); } function selectColumn(columnNumber) { colNum = columnNumber; $('#carousel-image').val(''); $('#carousel-image').on("change", () => { syncCarouselPreviewImage('carousel-image'); }); $('#carousel-title').on("input", () => { syncCarouselPreviewValue('carousel-title', true); }); $('#carousel-text').on("input", () => { syncCarouselPreviewValue('carousel-text', false); }); $('#carousel-action-1').on("input", () => { syncCarouselPreviewValue('carousel-action-1', true); }); $('#carousel-action-1-data').on("input", () => { syncCarouselPreviewValue('carousel-action-1-data', false); }); $('#carousel-action-2').on("input", () => { syncCarouselPreviewValue('carousel-action-2', true); }); $('#carousel-action-2-data').on("input", () => { syncCarouselPreviewValue('carousel-action-2-data', false); }); $('#carousel-action-3').on("input", () => { syncCarouselPreviewValue('carousel-action-3', true); }); $('#carousel-action-3-data').on("input", () => { syncCarouselPreviewValue('carousel-action-3-data', false); }); $('#carousel .dropdown-menu a').on("click", (e) => { syncCarouselPreviewButtonValue(e.currentTarget); }); setColumnValueToOriginal('carousel-title'); setColumnValueToOriginal('carousel-text'); setColumnValueToOriginal('carousel-action-1'); setColumnValueToOriginal('carousel-action-1-data'); setColumnButtonValueToOriginal('carousel-action-1-type'); setColumnValueToOriginal('carousel-action-2'); setColumnValueToOriginal('carousel-action-2-data'); setColumnButtonValueToOriginal('carousel-action-2-type'); setColumnValueToOriginal('carousel-action-3'); setColumnValueToOriginal('carousel-action-3-data'); setColumnButtonValueToOriginal('carousel-action-3-type'); function setColumnValueToOriginal(elementName) { let previewElem = $(`#preview-${elementName}-${colNum}`); let originalElem = $(`#${elementName}`); originalElem[0].value = previewElem[0].innerText; } function setColumnButtonValueToOriginal(elementName) { let previewElem = $(`#preview-${elementName}-${colNum}`); let originalElem = $(`#${elementName}`); originalElem[0].innerText = previewElem[0].innerText; } function syncCarouselPreviewValue(elementName, hideWithoutValue) { let previewElem = $(`#preview-${elementName}-${colNum}`); let originalElem = $(`#${elementName}`); if (hideWithoutValue) { if (originalElem[0].value === "" && !previewElem.hasClass("hide")) { previewElem.addClass("hide"); } else if (originalElem[0].value !== "" && previewElem.hasClass("hide")) { previewElem.removeClass("hide"); } } previewElem[0].innerText = originalElem[0].value; } function syncCarouselPreviewButtonValue(element) { let originalElem = $(element).parents('div:first').children('.btn:first'); let previewElem = $(`#preview-${originalElem[0].id}-${colNum}`); previewElem[0].innerText = originalElem[0].innerText; } function syncCarouselPreviewImage(elementName) { var reader = new FileReader(); reader.onload = function (event) { let previewElem = $(`#preview-${elementName}-${colNum}`); if (previewElem.hasClass("hide")) { previewElem.removeClass("hide"); } // Render thumbnail. event.target.result; previewElem.css("background-image", `url(${event.target.result})`); }; // Read in the image file as a data URL. reader.readAsDataURL($(`#${elementName}`)[0].files[0]); } } function sendCarouselFromBot() { let data = { "type": "template", "altText": "this is a buttons template", "template": { "type": "carousel", "imageAspectRatio": "rectangle", "imageSize": "cover", "columns": [ ] } } for (let i = 0; i < $('#preview-chat-template-carousel')[0].children.length; i++) { let column = { "actions": [ ] } if ($(`#preview-carousel-image-${i}`)[0].style['background-image'] !== "") { column.thumbnailImageUrl = $(`#preview-carousel-image-${i}`)[0].style['background-image']; column.imageBackgroundColor = "#000000"; } if ($(`#preview-carousel-title-${i}`)[0].innerText !== "") { column.title = $(`#preview-carousel-title-${i}`)[0].innerText; } column.text = $(`#preview-carousel-text-${i}`)[0].innerText; for (let ai = 1; ai < 4; ai++) { if ($(`#preview-carousel-action-${ai}-${i}`)[0].innerText !== "") { let type = $(`#preview-carousel-action-${ai}-type-${i}`)[0].innerText; if (type === "message") { column.actions.push({ "type": type, "label": $(`#preview-carousel-action-${ai}-${i}`)[0].innerText, "text": $(`#preview-carousel-action-${ai}-data-${i}`)[0].innerText }) } else if (type === "postback") { column.actions.push({ "type": type, "label": $(`#preview-carousel-action-${ai}-${i}`)[0].innerText, "text": $(`#preview-carousel-action-${ai}-${i}`)[0].innerText, "data": $(`#preview-carousel-action-${ai}-data-${i}`)[0].innerText }) } else if (type === "uri") { column.actions.push({ "type": type, "label": $(`#preview-carousel-action-${ai}-${i}`)[0].innerText, "uri": $(`#preview-carousel-action-${ai}-data-${i}`)[0].innerText }) } } } data.template.columns.push(column); } let li = parseDataAndReturnListItem(data); appendBotReplyToThread(li); $('#preview-chat-template-carousel')[0].children.remove(); } // Image Carousel var imgColNum = 0; function removeImageCarouselPreviewImage(elementName) { $(`#${elementName}`).val(''); let previewElement = $(`#preview-${elementName}-${imgColNum}`); previewElement.css("background-image", ``); previewElement.addClass('hide'); } function addImageColumn() { imgColNum = $('#preview-chat-template-image-carousel')[0].children.length; $('#preview-chat-template-image-carousel').append( `<div class="chat-template-image-carousel" onclick='selectImageColumn(${imgColNum})'> <div class="chat-template-image-carousel-image" id="preview-image-carousel-image-${imgColNum}"></div> <div class="chat-template-image-carousel-button"> <div class="chat-template-image-carousel-button-content" id="preview-image-carousel-action-${imgColNum}"></div> <div class="hide" id="preview-image-carousel-action-data-${imgColNum}"></div> <div class="hide" id="preview-image-carousel-action-type-${imgColNum}">message</div> </div> </div>` ); selectImageColumn(imgColNum); } function removeImageColumn() { $('#preview-chat-template-image-carousel')[0].children[imgColNum].remove(); } function selectImageColumn(columnNumber) { imgColNum = columnNumber; $('#image-carousel-image').val(''); $('#image-carousel-image').on("change", () => { syncImageCarouselPreviewImage('image-carousel-image'); }); $('#image-carousel-action').on("input", () => { syncImageCarouselPreviewValue('image-carousel-action', true); }); $('#image-carousel-action-data').on("input", () => { syncImageCarouselPreviewValue('image-carousel-action-data', false); }); $('#imagecarousel .dropdown-menu a').on("click", (e) => { syncImageCarouselPreviewButtonValue(e.currentTarget); }); setImageColumnValueToOriginal('image-carousel-action'); setImageColumnValueToOriginal('image-carousel-action-data'); setImageColumnButtonValueToOriginal('image-carousel-action-type'); function setImageColumnValueToOriginal(elementName) { let previewElem = $(`#preview-${elementName}-${imgColNum}`); let originalElem = $(`#${elementName}`); originalElem[0].value = previewElem[0].innerText; } function setImageColumnButtonValueToOriginal(elementName) { let previewElem = $(`#preview-${elementName}-${imgColNum}`); let originalElem = $(`#${elementName}`); originalElem[0].innerText = previewElem[0].innerText; } function syncImageCarouselPreviewValue(elementName, hideWithoutValue) { let previewElem = $(`#preview-${elementName}-${imgColNum}`); let originalElem = $(`#${elementName}`); if (hideWithoutValue) { if (originalElem[0].value === "" && !previewElem.hasClass("hide")) { previewElem.addClass("hide"); } else if (originalElem[0].value !== "" && previewElem.hasClass("hide")) { previewElem.removeClass("hide"); } } previewElem[0].innerText = originalElem[0].value; } function syncImageCarouselPreviewButtonValue(element) { let originalElem = $(element).parents('div:first').children('.btn:first'); let previewElem = $(`#preview-${originalElem[0].id}-${imgColNum}`); previewElem[0].innerText = originalElem[0].innerText; } function syncImageCarouselPreviewImage(elementName) { var reader = new FileReader(); reader.onload = function (event) { let previewElem = $(`#preview-${elementName}-${imgColNum}`); if (previewElem.hasClass("hide")) { previewElem.removeClass("hide"); } // Render thumbnail. event.target.result; previewElem.css("background-image", `url(${event.target.result})`); }; // Read in the image file as a data URL. reader.readAsDataURL($(`#${elementName}`)[0].files[0]); } } function sendImageCarouselFromBot() { let data = { "type": "template", "altText": "this is a buttons template", "template": { "type": "image_carousel", "columns": [ ] } } for (let i = 0; i < $('#preview-chat-template-image-carousel')[0].children.length; i++) { let column = { "imageUrl": $(`#preview-image-carousel-image-${i}`)[0].style['background-image'] } let type = $(`#preview-image-carousel-action-type-${i}`)[0].innerText; if (type === "message") { column.action = { "type": type, "label": $(`#preview-image-carousel-action-${i}`)[0].innerText, "text": $(`#preview-image-carousel-action-data-${i}`)[0].innerText }; } else if (type === "postback") { column.action = { "type": type, "label": $(`#preview-image-carousel-action-${i}`)[0].innerText, "text": $(`#preview-image-carousel-action-${i}`)[0].innerText, "data": $(`#preview-image-carousel-action-data-${i}`)[0].innerText }; } else if (type === "uri") { column.action = { "type": type, "label": $(`#preview-image-carousel-action-${i}`)[0].innerText, "uri": $(`#preview-image-carousel-action-data-${i}`)[0].innerText }; } data.template.columns.push(column); } let li = parseDataAndReturnListItem(data); appendBotReplyToThread(li); $('#preview-chat-template-image-carousel')[0].children.remove(); } //#endregion //#region menus function toggleKeyboard() { var keyboard = $('.chat-keyboard'); var chatthread = $('.chat-thread'); chatthread.removeClass('richmenu'); $('.chat-richmenu').removeClass('visible'); $('.chat-bar').addClass('visible'); $('.chat-bar-richmenu').removeClass('visible'); if (keyboard.hasClass('visible')) { keyboard.removeClass('visible'); chatthread.removeClass('keyboard') } else { keyboard.addClass('visible'); chatthread.addClass('keyboard'); } $('.chat-thread li').last().focus(); } var zoom = 1; function zoomin() { var rootStyle = window.getComputedStyle($(':root')[0]); zoom += 0.1; $('.simulator')[0].style.transform = `scale(${zoom})`; } function zoomout() { zoom -= 0.1; $('.simulator')[0].style.transform = `scale(${zoom})`; } function refresh() { $(".chat-thread ul").children().remove(); $(".chat-thread ul").append('<li class="chat-top-space"></li>'); } function toggleMoreMenu() { if ($('.moreMenu').hasClass("hide")) { $('.moreMenu').removeClass("hide"); } else { $('.moreMenu').addClass("hide"); } } function toggleRichMenu() { let richmenu = $('.chat-richmenu'); let chatthread = $('.chat-thread'); let chatbar = $('.chat-bar'); let chatbarrichmenu = $('.chat-bar-richmenu'); $('.chat-keyboard').removeClass('visible'); chatthread.removeClass('keyboard'); if (richmenu.hasClass('visible')) { richmenu.removeClass('visible'); chatthread.removeClass('richmenu'); chatbarrichmenu.removeClass('visible'); chatbar.addClass('visible'); } else { $.ajax({ url: `/richmenu/${localStorage.getItem('userId')}/${localStorage.getItem('richMenuId')}`, type: "GET", success: function (data) { if (data.message === "no menu") { localStorage.removeItem('richMenuId'); window.alert("no rich menu for the user"); // As there is no menu, do nothing. return; } else if (data == "") { // As richmenu id didnt changed, do nothing but show rich menu. } else { localStorage.setItem('richMenuId', data.richMenu.richMenuId); richmenu[0].innerHTML = ""; let imgDiv = `<img src="data:image/png;base64,${_arrayBufferToBase64(data.image.data)}" usemap="#richmenumap"/><map name="richmenumap">`; let scale = Number($(':root').css('--chat-width').replace('px', '')) / data.richMenu.size.width; for (let i = 0; i < data.richMenu.areas.length; i++) { let area = data.richMenu.areas[i]; if (area.action.type === "uri") { imgDiv += `<area shape="rect" coords="${area.bounds.x * scale},${area.bounds.y * scale},${area.bounds.width * scale + area.bounds.x * scale},${area.bounds.height * scale + area.bounds.y * scale}" href="${area.action.uri}" target="_blank">`; } else if (area.action.type === "message") { imgDiv += `<area shape="rect" coords="${area.bounds.x * scale},${area.bounds.y * scale},${area.bounds.width * scale + area.bounds.x * scale},${area.bounds.height * scale + area.bounds.y * scale}" href="javascript:sendTextMessage('${area.action.text}');">`; } else if (area.action.type === "postback") { if(area.action.text){ imgDiv += `<area shape="rect" coords="${area.bounds.x * scale},${area.bounds.y * scale},${area.bounds.width * scale + area.bounds.x * scale},${area.bounds.height * scale + area.bounds.y * scale}" href="javascript:sendPostback('${area.action.data}');sendTextMessage('${area.action.text}');">`; } else{ imgDiv += `<area shape="rect" coords="${area.bounds.x * scale},${area.bounds.y * scale},${area.bounds.width * scale + area.bounds.x * scale},${area.bounds.height * scale + area.bounds.y * scale}" href="javascript:sendPostback('${area.action.data}');">`; } } } imgDiv += `</map>` $(':root').css('--chat-richmenu-height', scale * data.richMenu.size.height + 'px'); richmenu.append(imgDiv); $('.chat-bar-richmenu-item')[0].innerText = data.richMenu.chatBarText; } richmenu.addClass('visible'); chatthread.addClass('richmenu'); chatbarrichmenu.addClass('visible'); chatbar.removeClass('visible'); $('.chat-thread li').last().focus(); } }); } } function _arrayBufferToBase64(buffer) { var binary = ''; var bytes = new Uint8Array(buffer); var len = bytes.byteLength; for (var i = 0; i < len; i++) { binary += String.fromCharCode(bytes[i]); } return window.btoa(binary); } function toggleSettings() { if ($('.settings').hasClass("hide")) { $('.settings').removeClass("hide"); } else { $('.settings').addClass("hide"); } } function closeChatRaw() { if (!$('.chat-raw').hasClass("hide")) { $('.chat-raw').addClass("hide"); } } var numOfSim = 1; function addSimulator() { var newSimulator = $('.simulator:first').clone(); newSimulator.addClass(`simulator${numOfSim}`); numOfSim++; $('.simulator:last').after(newSimulator); } function saveChat() { let data = []; $('.chat-thread li').each(function () { if ($(this).attr('data') != null) { let jsonData = JSON.parse($(this).attr('data')); // If this is media, then save src as part of export information. if ($(this).children('img').attr('src') != null) { jsonData.path = $(this).children('img').attr('src'); } data.push(jsonData); } }); var a = document.createElement('a'); a.download = "export_chat.json"; a.href = 'data:application/json,' + encodeURIComponent(JSON.stringify(data, null, '\t')); a.click(); } function openFileDialogForLoadJson() { $('#loadJsonFile').trigger("click"); } // Load saved chat file function loadJson() { var reader = new FileReader(