{"version":3,"file":"script.min.js","sources":["script.min.js"],"sourcesContent":["/*\n * Requirements\n * - each star has same width\n * - container #rating is empty\n */\n\nvar likeKnob = function (ratingEl, uuid, optionsParam) {\n var maxWidth = 215; // max width of rating bar and tooltip\n var defaultOptions = {\n tooltipMessageWhenRatingAlreadySent: \"Already sent!\",\n tooltipMessageWhenRatingIncomplete: \"Specify a Rating first!\",\n tooltipMessageWhenRatingSent: \"Rating sent!\",\n tooltipMessageWhenSentFailed:\n \"Couldn't send rating to server! Could you try again?\",\n tooltipDisplayInMS: 2500,\n cssReset: false,\n question: \"What did you not like about this page?\",\n inputPlaceholder: \"Type answer here...\",\n devMode: {\n bool: false, // general dev mode switch, further options will not do anything if this is disabled // changes url to localhost\n url: \"\", // url to change where data is being sent\n sendData: true, // when false, sends & saves no data\n },\n ratingBarContainerClass: \"\", // all class options are directly set to the className attribute in JS, so multiple classes are separated through a space\n questionContainerClass: \"\",\n questionClass: \"\",\n inputClass: \"\",\n buttonContainerClass: \"\",\n sendButtonClass: \"\",\n ratingBarContainerStyle:\n \"display: block; position:relative; max-width: \" + maxWidth + \"px;\",\n questionContainerStyle: \"display: block;\" + \"margin-top: 1.5rem;\",\n questionStyle:\n \"font-family: sans-serif;\" + \"color: #000;\" + \"font-size: 100%;\",\n inputStyle:\n \"background-color: #f7f7f7;\" +\n \"outline: none;\" +\n \"border: none;\" +\n \"padding: .5rem;\" +\n \"font-family: sans-serif;\" +\n \"width: 100%;\" +\n \"font-size: 100%;\" +\n \"color: #6e6e6e;\" +\n \"box-sizing: border-box;\" +\n \"margin-top: .5rem;\",\n buttonContainerStyle: \"\",\n sendButtonStyle:\n \"cursor: pointer;\" +\n \"padding: .5rem;\" +\n \"margin-top: 1rem;\" +\n \"background: #000;\" +\n \"color: #fff;\" +\n \"font-family: sans-serif;\" +\n \"transition: transform 0.5s ease;\" +\n \"border: none;\",\n sendButtonHoverTransform: true,\n tooltipStyle:\n \"width: \" +\n maxWidth +\n \"px;\" +\n \"background-color: #666666;\" +\n \"color: #ffffff;\" +\n \"text-align: center;\" +\n \"padding: 5px 0;\" +\n \"border-radius: 5px;\" +\n \"position: absolute;\" +\n \"z-index: 1;\" +\n \"bottom: 125%;\" +\n \"left: 50%;\" +\n \"margin-left: -\" +\n maxWidth / 2 +\n \"px;\" +\n \"opacity: 0;\" +\n \"transition: opacity 0.6s;\",\n };\n\n var options = Object.assign(defaultOptions, optionsParam);\n\n // Check if Question meets Backend Criteria\n if (options.question.length > 140) {\n console.error(\n \"LikeKnob Script Error: The Question specified '\" +\n options.question +\n \"' is too long! Should be not more than 140 chars, the current length is: \" +\n options.question.length\n );\n }\n\n //\n // #1 - Creation of Elements\n //\n\n var cssReset = options.cssReset ? \"all:unset;\" : \"\";\n\n // first create the rating Elements\n function svgStar(last) {\n var marginRight = last ? \"\" : \"margin-right: 8%;\";\n\n var svgStar =\n '\\n' +\n ' ';\n\n return svgStar;\n }\n\n var ratingBarContainerEl = document.createElement(\"div\");\n\n ratingBarContainerEl.style = cssReset + options.ratingBarContainerStyle;\n ratingBarContainerEl.className = options.ratingBarContainerClass;\n\n ratingEl.appendChild(ratingBarContainerEl);\n\n for (var i = 0; i < 5; i++) {\n var last = false;\n if (i === 4) {\n last = true;\n }\n\n ratingBarContainerEl.innerHTML =\n ratingBarContainerEl.innerHTML + svgStar(last);\n }\n\n var stars = ratingBarContainerEl.getElementsByTagName(\"svg\");\n\n // Add a tooltip for errors and so on\n var tooltipEl = document.createElement(\"span\");\n tooltipEl.style = cssReset + options.tooltipStyle;\n\n var tooltipArrowEl = document.createElement(\"span\");\n tooltipArrowEl.style =\n cssReset +\n 'content: \"\";' +\n \"position: absolute;\" +\n \"top: 100%;\" +\n \"left: 50%;\" +\n \"margin-left: -5px;\" +\n \"border-width: 5px;\" +\n \"border-style: solid;\" +\n \"border-color: #555 transparent transparent transparent;\";\n\n var tooltipTextEl = document.createElement(\"span\");\n tooltipTextEl.style = cssReset + \"font-family: sans-serif;\";\n\n tooltipEl.appendChild(tooltipTextEl);\n tooltipEl.appendChild(tooltipArrowEl);\n\n ratingBarContainerEl.appendChild(tooltipEl);\n\n // create question p\n var questionContainerEl = document.createElement(\"div\");\n questionContainerEl.style = cssReset + options.questionContainerStyle;\n questionContainerEl.className = options.questionContainerClass;\n\n ratingEl.appendChild(questionContainerEl);\n\n var questionEl = document.createElement(\"p\");\n questionEl.style = cssReset + options.questionStyle;\n questionEl.textContent = options.question;\n questionEl.className = options.questionClass;\n\n questionContainerEl.appendChild(questionEl);\n\n // then create the input field\n var inputElement = document.createElement(\"input\");\n inputElement.type = \"text\";\n inputElement.placeholder = options.inputPlaceholder;\n inputElement.maxLength = 140;\n inputElement.style = cssReset + options.inputStyle;\n inputElement.className = options.inputClass;\n\n questionContainerEl.appendChild(inputElement);\n\n // create send Button Container\n var buttonContainer = document.createElement(\"div\");\n buttonContainer.style = cssReset + options.buttonContainerStyle;\n buttonContainer.className = options.buttonContainerClass;\n\n ratingEl.appendChild(buttonContainer);\n\n // create send button\n var sendButtonEl = document.createElement(\"button\");\n sendButtonEl.textContent = \"Send it!\";\n sendButtonEl.style = cssReset + options.sendButtonStyle;\n sendButtonEl.className = options.sendButtonClass;\n\n buttonContainer.appendChild(sendButtonEl);\n\n //\n // #2 - Event Listeners\n //\n var ratingSent = false;\n\n // will be sent to LikeKnob API\n const ratingObject = {\n rating: undefined,\n message: undefined,\n url: window.location.pathname,\n question: options.question.slice(0, 140), // strip the question, if necessary to 140 chars, because of backend requirements\n };\n\n // current number of filled stars\n // used when user clicks that rating is saved\n var tempRating = undefined;\n\n ratingBarContainerEl.addEventListener(\"mousemove\", function (e) {\n if (ratingSent) {\n // rating already set, don't set new one\n return;\n }\n\n const mousePos = e.clientX;\n\n // iterate throught stars array backwards\n // if we wouldn't, we had to call fillToStarNumber in some cases 5 times\n // like this, we check the most right star first and break the loop\n for (var i = 4; i >= 0; i--) {\n const rectStar = stars[i].getBoundingClientRect();\n const positionTriggerStar = rectStar.x + rectStar.width * 0.3; // when over 30% of star\n\n if (mousePos >= positionTriggerStar) {\n // triggerered the i+1th Star\n\n // hold this rating ready for saving\n tempRating = i + 1;\n\n fillToStarNumber(i + 1);\n break;\n }\n }\n });\n\n ratingBarContainerEl.addEventListener(\"click\", function (e) {\n if (ratingSent) {\n // should display error message\n // don't save new rating\n displayTooltip(options.tooltipMessageWhenRatingAlreadySent);\n return;\n }\n\n // save data on click for sending\n if (typeof tempRating === \"number\") {\n // tempRating is defined\n // user set rating\n // let's save it for sending to API\n ratingObject.rating = tempRating;\n }\n });\n\n ratingBarContainerEl.addEventListener(\"mouseout\", function (e) {\n var rating = ratingObject.rating;\n if (typeof rating === \"number\") {\n // rating defined\n fillToStarNumber(rating);\n } else {\n // no rating saved so clear stars in UI\n fillToStarNumber(0);\n }\n });\n\n inputElement.addEventListener(\"keypress\", async function (e) {\n if (e.key === \"Enter\" || e.keyCode === 13) {\n // Send the rating\n if (ratingSent) {\n // Rating already sent\n displayTooltip(options.tooltipMessageWhenRatingAlreadySent);\n return;\n }\n\n if (typeof ratingObject.rating === \"undefined\") {\n // Throw Error, specify an rating first\n displayTooltip(options.tooltipMessageWhenRatingIncomplete);\n return;\n }\n\n ratingObject.message = this.value;\n\n disableSending();\n await saveAndSend(ratingObject.rating, this.value);\n displayTooltip(options.tooltipMessageWhenRatingSent);\n }\n });\n\n sendButtonEl.addEventListener(\"click\", async function (e) {\n if (ratingSent) {\n // Rating already sent\n displayTooltip(options.tooltipMessageWhenRatingAlreadySent);\n return;\n }\n\n if (typeof ratingObject.rating === \"undefined\") {\n // Throw Error, specify an rating first\n displayTooltip(options.tooltipMessageWhenRatingIncomplete);\n return;\n }\n\n ratingObject.message = inputElement.value;\n disableSending();\n await saveAndSend(ratingObject.rating, ratingObject.message);\n\n displayTooltip(options.tooltipMessageWhenRatingSent);\n });\n\n if (options.sendButtonHoverTransform) {\n sendButtonEl.addEventListener(\"mouseover\", function () {\n this.style.transform = \"scale(0.9)\";\n });\n\n sendButtonEl.addEventListener(\"mouseleave\", function (e) {\n this.style.transform = \"\";\n });\n }\n\n // get rating from storage\n checkForRatingInStorage();\n if (ratingSent) {\n fillToStarNumber(ratingObject.rating);\n inputElement.value = ratingObject.message; // set the input field to the already sent rating\n disableSending();\n }\n\n function fillSVG(element) {\n element.style.fill = \"#FFD23F\";\n }\n\n function unfillSVG(element) {\n element.style.fill = \"\";\n }\n\n function fillToStarNumber(number) {\n // unfill all stars\n for (var star of stars) {\n unfillSVG(star.getElementsByTagName(\"path\")[0]);\n }\n\n if (number !== 0) {\n // fill to star number\n for (var index of [...Array(number).keys()]) {\n fillSVG(stars[index].getElementsByTagName(\"path\")[0]);\n }\n }\n }\n\n function disableSending() {\n inputElement.disabled = true;\n inputElement.style = options.inputStyle + \"opacity: 0.7;\";\n sendButtonEl.style = options.sendButtonStyle + \"opacity: 0;\";\n }\n\n function enableSending() {\n inputElement.disabled = false;\n inputElement.style = cssReset + options.inputStyle;\n sendButtonEl.style = cssReset + options.sendButtonStyle;\n }\n\n async function sendRatingToServer() {\n var url;\n if (options.devMode.bool) {\n url = options.devMode.url + \"/api/v0/websites/\" + uuid + \"/rating\";\n } else {\n url = \"https://app.likeknob.com/api/v0/websites/\" + uuid + \"/rating\";\n }\n\n try {\n await fetch(url, {\n method: \"POST\",\n body: JSON.stringify(ratingObject),\n headers: {\n \"Content-Type\": \"application/json\",\n },\n });\n } catch (e) {\n enableSending();\n displayTooltip(options.tooltipMessageWhenSentFailed);\n throw Error(\"Rating failed to sent!\");\n }\n }\n\n function checkForRatingInStorage() {\n if (typeof localStorage.likeKnobRatingArray !== \"undefined\") {\n var likeKnobRatingArray = JSON.parse(localStorage.likeKnobRatingArray);\n var key = window.location.pathname;\n\n if (typeof likeKnobRatingArray[key] !== \"undefined\") {\n ratingSent = true;\n ratingObject.message = likeKnobRatingArray[key].message;\n ratingObject.rating = likeKnobRatingArray[key].rating;\n }\n }\n }\n\n function displayTooltip(message) {\n tooltipEl.style = cssReset + options.tooltipStyle + \"opacity: 1;\";\n tooltipTextEl.textContent = message;\n\n setTimeout(function () {\n tooltipEl.style = cssReset + options.tooltipStyle;\n }, options.tooltipDisplayInMS);\n }\n\n async function saveAndSend(rating, message) {\n if (options.devMode.bool && !options.devMode.sendData) {\n return;\n }\n\n if (ratingSent) {\n // rating already sent\n return;\n }\n\n if (typeof localStorage.likeKnobRatingArray === \"undefined\") {\n localStorage.likeKnobRatingArray = JSON.stringify({});\n }\n\n var key = window.location.pathname;\n\n var likeKnobRatingArray = JSON.parse(localStorage.likeKnobRatingArray);\n\n if (typeof likeKnobRatingArray[key] !== \"undefined\") {\n // error, already object in storage\n // don't save or send anything\n return;\n }\n\n await sendRatingToServer(rating, message);\n\n ratingSent = true;\n\n likeKnobRatingArray[key] = {\n rating: rating,\n message: message,\n };\n\n localStorage.likeKnobRatingArray = JSON.stringify(likeKnobRatingArray);\n }\n};\n"],"names":["likeKnob","ratingEl","uuid","optionsParam","options","Object","assign","tooltipMessageWhenRatingAlreadySent","tooltipMessageWhenRatingIncomplete","tooltipMessageWhenRatingSent","tooltipMessageWhenSentFailed","tooltipDisplayInMS","cssReset","question","inputPlaceholder","devMode","bool","url","sendData","ratingBarContainerClass","questionContainerClass","questionClass","inputClass","buttonContainerClass","sendButtonClass","ratingBarContainerStyle","questionContainerStyle","questionStyle","inputStyle","buttonContainerStyle","sendButtonStyle","sendButtonHoverTransform","tooltipStyle","length","console","error","ratingBarContainerEl","document","createElement","style","className","appendChild","i","innerHTML","stars","getElementsByTagName","tooltipEl","tooltipArrowEl","tooltipTextEl","questionContainerEl","questionEl","textContent","inputElement","type","placeholder","maxLength","buttonContainer","sendButtonEl","ratingSent","ratingObject","rating","undefined","message","window","location","pathname","slice","tempRating","fillToStarNumber","number","star","fill","index","Array","keys","disableSending","disabled","addEventListener","e","mousePos","clientX","rectStar","getBoundingClientRect","x","width","displayTooltip","async","key","keyCode","this","value","saveAndSend","transform","likeKnobRatingArray","localStorage","JSON","parse","checkForRatingInStorage","sendRatingToServer","fetch","method","body","stringify","headers","Content-Type","Error","setTimeout"],"mappings":"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"}