/** * * @param {HTMLElement} parentDiv */ window.LGWIDGET.thumbs_up_thumbs_down = function (parentDiv) { const renderResults = (results = []) => { // { // "ok": 1, // "data": [ // { // "_id": "no", // "count": 2 // }, // { // "_id": "yes", // "count": 3 // } // ] // } const items = { Yes: 0, No: 0, } const total = results.reduce((acc, result) => acc + result.count, 0) results.forEach(result => { const percentage = result.count / total * 100 items[result._id] = percentage.toFixed(1) }) const orderedResults = [ { label: 'Yes', percentage: items['Yes'] }, { label: 'No', percentage: items['No'] }, ] let renderedResults = `
` for (const row of orderedResults) { renderedResults += `
${row.label}
${row.percentage}%
` } renderedResults += '
' return renderedResults } // Generate a unique class to scope everything to. // https://stackoverflow.com/questions/1349404/generate-random-string-characters-in-javascript const unique_id = `c${(Math.random() + 1).toString(36).substring(7)}` const base_class = `thumbs-up-down${unique_id}` const { site = '', slug = '', question = '', thumbs_up_text = 'Yes', thumbs_down_text = 'No', settings = '{}', results = 'false', thanks = 'Thank you for your feedback', } = parentDiv.dataset let { url = 'https://api.leafmedia.io/widget', } = parentDiv.dataset if (results === 'true') { url = `${url}?results=true` } // local storage check const storageKey = `LGWIDGET.thumbs-up-down:${question}` const voted = localStorage.getItem(storageKey) ?? 'false' if (voted === 'true') { return } const objToStyle = obj => Object.entries(obj) .reduce((acc, [key, value]) => (`${acc }${key}: ${value};`), '') let parsed = {} try { parsed = JSON.parse(settings) // eslint-disable-next-line no-empty } catch (e) {} const { base = {}, base_question = {}, base_container = {}, base_item = {}, base_item__hover = {}, base_thumbs_up = {}, base_thumbs_down = {}, base_thumbs_up__hover = {}, base_thumbs_down__hover = {}, base_thanks = {}, results_row = {}, results_row__labels = {}, results_bar_color = '#008eff', } = parsed const base_style = { display: 'flex', 'flex-direction': 'column', 'justify-content': 'space-between', gap: '15px', padding: '20px', 'background-color': '#fff', ...base, } const base_question_style = { 'text-align': 'center', 'font-size': '30px', ...base_question, } const base_container_style = { display: 'flex', 'justify-content': 'space-between', gap: '15px', ...base_container, } const base_item_style = { height: '50px', display: 'flex', flex: '1', 'justify-content': 'center', 'align-items': 'center', 'font-size': '20px', 'background-color': '#eee', ...base_item, } const base_item__hover_style = { cursor: 'pointer', ...base_item__hover, } const base_thumbs_up_style = { ...base_thumbs_up, } const base_thumbs_down_style = { ...base_thumbs_down, } const base_thumbs_up__hover_style = { ...base_thumbs_up__hover, } const base_thumbs_down__hover_style = { ...base_thumbs_down__hover, } const base_thanks_style = { height: '50px', display: 'flex', flex: '1', 'justify-content': 'center', 'align-items': 'center', 'font-size': '20px', ...base_thanks, } const results_row_style = { display: 'flex', 'justify-content': 'space-between', gap: '10px', 'margin-bottom': '5px', height: '30px', ...results_row, } const results_row__labels_style = { width: '45px', display: 'flex', 'justify-content': 'center', 'align-items': 'center', ...results_row__labels, } const results_row__percentage_style = { ...results_row__labels_style, 'justify-content': 'right', } const thanksHtml = `
${thanks}
` parentDiv.innerHTML = `
${question}
${thumbs_up_text}
${thumbs_down_text}
` const $thumbs = document.querySelectorAll(`.${base_class}-item`) $thumbs.forEach($thumb => { $thumb.addEventListener('click', e => { if (voted === 'true') { return } // localStorage.setItem(storageKey, 'true') // voted = 'true' // todo uncomment local storage const $classList = e.target.classList const key = $classList.contains('thumbs-up') ? thumbs_up_text : thumbs_down_text const answer = {} answer[key] = 1 const payload = { site, slug, type: 'thumbs-up-down', prompt: question, answer, } let response = [] fetch(url, { method: 'POST', headers: { 'Content-Type': 'application/json', }, body: JSON.stringify(payload), }) .then(r => r.json()) .then(r => response = r) .catch(e => console.error(e)) .finally(() => { const $element = document.querySelector(`.${base_class}-container`) // if epmd response fails, just show thanks if (!Array.isArray(response)) { return $element.innerHTML = thanksHtml } if (results === 'true') { return $element.innerHTML = renderResults(response) } return $element.innerHTML = thanksHtml }) }) }) }