diff --git a/dist/mailymaily-min.js b/dist/mailymaily-min.js index 63b1f4e..e77548d 100644 --- a/dist/mailymaily-min.js +++ b/dist/mailymaily-min.js @@ -1 +1 @@ -var mailymailyApp=mailymailyApp||{};!function(t){var e=document.getElementsByTagName("html")[0],o=document.getElementsByTagName("body")[0],i=null,n=null,l=' ',a=' ',r=new Object;r.linkClass="mailymaily",r.autoClose=!0,r.disableOnMobile=!0,r.title="Compose new email with",r.buttonText1="Gmail in browser",r.buttonText2="Outlook in browser",r.buttonText3="Yahoo in browser",r.buttonText4="Default email app",r.buttonIcon1=l,r.buttonIcon2=l,r.buttonIcon3=l,r.buttonIcon4=' ',r.buttonIconCopy=a,r.buttonTextCopy="Copy",r.buttonTextCopyAction="Copied!";var c=0,s="auto";t.buildStyleTag=function(){var e=document.createElement("style"),o=".mailymaily-modal{background-color:#000;background-color:rgba(0,0,0,.4);bottom:0;color:#303131;display:none;height:100%;left:0;margin:0;padding:0;position:fixed;right:0;top:0;width:100%;z-index:1000}.mailymaily-modal-content{-webkit-animation:mailymaily-appear .4s;animation:mailymaily-appear .4s;background-color:#f1f5f8;border-radius:8px;bottom:auto;-webkit-box-shadow:0 4px 8px 0 rgba(0,0,0,.2),0 6px 20px 0 rgba(0,0,0,.19);box-shadow:0 4px 8px 0 rgba(0,0,0,.2),0 6px 20px 0 rgba(0,0,0,.19);left:50%;max-height:calc(100% - 100px);overflow:auto;padding:0;position:fixed;right:-45%;top:50%;-webkit-transform:translate(-50%,-50%);transform:translate(-50%,-50%)}.mailymaily-modal-content:focus,.mailymaily-modal-content:hover{overflow-y:auto}@media only screen and (min-width:768px){.mailymaily-modal-content{right:auto}}.mailymaily-modal-head{-webkit-box-align:center;-ms-flex-align:center;align-items:center;background-color:#fff;clear:both;display:-webkit-box;display:-ms-flexbox;display:flex;min-width:0;padding:10px 20px}.mailymaily-modal-title{color:#303131;-webkit-box-flex:1;-ms-flex:1;flex:1;font-family:sans-serif;font-size:120%;font-weight:700;margin:0;overflow:hidden;padding:0;text-overflow:ellipsis;white-space:nowrap}.mailymaily-modal-close{color:#aaa;-webkit-box-flex:initial;-ms-flex:initial;flex:initial;font-size:38px;margin-left:20px;position:relative;text-align:right;text-decoration:none;top:-4px}.mailymaily-modal-close:focus,.mailymaily-modal-close:hover{color:#000;cursor:pointer;font-weight:700;outline:0}.mailymaily-modal-body{height:100%;padding:20px}.mailymaily-button{color:#333;text-decoration:none}.mailymaily-button:focus{outline:0}.mailymaily-button:focus .mailymaily-button-content{background-color:#555;color:#fff}.mailymaily-button-content{background-color:#fff;border:none;border-radius:8px;-webkit-box-shadow:0 2px 4px rgba(0,0,0,.18);box-shadow:0 2px 4px rgba(0,0,0,.18);margin-bottom:20px;overflow:hidden;padding:15px 20px;text-overflow:ellipsis;white-space:nowrap}.mailymaily-button-content:hover{background-color:#555;color:#fff}.mailymaily-button:last-child .mailymaily-button-content{margin-bottom:0}.mailymaily-button-icon{display:inline-block;font-weight:700;position:relative;top:4px}.mailymaily-button-icon svg{height:24px;width:24px}.mailymaily-button-text{display:inline-block;margin-left:5px;position:relative;top:-2px}.mailymaily-copy{border-radius:8px;-webkit-box-shadow:0 2px 4px rgba(0,0,0,.18);box-shadow:0 2px 4px rgba(0,0,0,.18);height:59px;margin-top:20px;position:relative}.mailymaily-button-copy{background-color:#fff;border:none;border-bottom-left-radius:8px;border-top-left-radius:8px;bottom:21px;color:#333;font-size:100%;height:100%;left:0;overflow:hidden;padding:15px 20px;position:absolute;text-overflow:ellipsis;top:0;white-space:nowrap;width:120px}.mailymaily-button-copy:focus,.mailymaily-button-copy:hover{background-color:#555;color:#fff;cursor:pointer;outline:0}.mailymaily-button-copy-clicked,.mailymaily-button-copy-clicked:focus,.mailymaily-button-copy-clicked:hover{background-color:#1f9d55;color:#fff}.mailymaily-button-copy-clicked .mailymaily-button-icon,.mailymaily-button-copy-clicked:focus .mailymaily-button-icon,.mailymaily-button-copy-clicked:hover .mailymaily-button-icon{display:none;visibility:hidden}.mailymaily-button-copy-clicked .mailymaily-button-text,.mailymaily-button-copy-clicked:focus .mailymaily-button-text,.mailymaily-button-copy-clicked:hover .mailymaily-button-text{color:#fff;top:2px}.mailymaily-email-address{background-color:#d8dcdf;border:none;border-radius:8px;-webkit-box-shadow:unset;box-shadow:unset;-webkit-box-sizing:border-box;box-sizing:border-box;color:#48494a;font-size:100%;height:100%;overflow:hidden;padding:20px 20px 20px 140px;text-overflow:ellipsis;white-space:nowrap;width:100%}.mailymaily-brand{color:#888;font-size:80%;margin-top:20px;text-align:center}.mailymaily-brand a{color:#888}.mailymaily-brand a:focus,.mailymaily-brand a:hover{font-weight:700;outline:0}.mailymaily-no-scroll{overflow:hidden;position:fixed;width:100%}.mailymaily-is-hidden{display:none;visibility:hidden}@-webkit-keyframes mailymaily-appear{0%{opacity:0;-webkit-transform:translate(-50%,-50%) scale(0,0);transform:translate(-50%,-50%) scale(0,0)}100%{opacity:1;-webkit-transform:translate(-50%,-50%) scale(1,1);transform:translate(-50%,-50%) scale(1,1)}}@keyframes mailymaily-appear{0%{opacity:0;-webkit-transform:translate(-50%,-50%) scale(0,0);transform:translate(-50%,-50%) scale(0,0)}100%{opacity:1;-webkit-transform:translate(-50%,-50%) scale(1,1);transform:translate(-50%,-50%) scale(1,1)}}";return o=o.replace(/mailymaily/g,t.prefix()),e.setAttribute("id",t.prefix("-styles")),e.setAttribute("type","text/css"),e.styleSheet?e.styleSheet.cssText=o:e.appendChild(document.createTextNode(o)),e},t.embedStyleTag=function(){if(!t.styleTagExists()){var e=document.head.firstChild;document.head.insertBefore(t.buildStyleTag(),e)}},t.styleTagExists=function(){return!!document.getElementById(t.prefix("-styles"))},t.buildModal=function(){var e=document.createElement("div"),o=`
${r.title}
×
`;return o=o.replace(/mailymaily/g,t.prefix()),e.setAttribute("id",t.prefix("-modal")),e.setAttribute("class",t.prefix("-modal")),e.setAttribute("style","display: none;"),e.setAttribute("aria-hidden",!0),e.innerHTML=o,e},t.embedModal=function(){if(!t.modalExists()){var e=t.buildModal(),o=document.body.firstChild;document.body.insertBefore(e,o)}},t.modalExists=function(){return!!document.getElementById(t.prefix("-modal"))},t.getModal=function(e){return t.hydrateModal(e),document.getElementById(t.prefix("-modal"))},t.hydrateModal=function(e){var o=t.getEmail(e),i=t.getLinkField(e,"subject"),n=t.getLinkField(e,"cc"),l=t.getLinkField(e,"bcc"),a=t.getLinkField(e,"body");document.getElementById(t.prefix("-button-1")).href="https://mail.google.com/mail/?view=cm&fs=1&to="+o+"&su="+i+"&cc="+n+"&bcc="+l+"&body="+a,document.getElementById(t.prefix("-button-2")).href="https://outlook.office.com/owa/?path=/mail/action/compose&to="+o+"&subject="+i+"&body="+a,document.getElementById(t.prefix("-button-3")).href="https://compose.mail.yahoo.com/?to="+o+"&subject="+i+"&cc="+n+"&bcc="+l+"&body="+a,document.getElementById(t.prefix("-button-4")).href="mailto:"+o+"?subject="+i+"&cc="+n+"&bcc="+l+"&body="+a,document.getElementById(t.prefix("-email-address")).innerHTML=o,document.getElementById(t.prefix("-button-icon-1")).innerHTML=r.buttonIcon1,document.getElementById(t.prefix("-button-icon-2")).innerHTML=r.buttonIcon2,document.getElementById(t.prefix("-button-icon-3")).innerHTML=r.buttonIcon3,document.getElementById(t.prefix("-button-icon-4")).innerHTML=r.buttonIcon4,document.getElementById(t.prefix("-button-icon-copy")).innerHTML=r.buttonIconCopy,t.toggleHideCopyUi(o)},t.savePageScrollPosition=function(){c=window.pageYOffset,o.style.top=-c+"px"},t.restorePageScrollPosition=function(){window.scrollTo(0,c),o.style.top=0},t.saveScrollBehavior=function(){s=e.style.scrollBehavior,e.style.scrollBehavior="auto"},t.restoreScrollBehavior=function(){e.style.scrollBehavior=s},t.saveLastDocElementFocused=function(){n=document.activeElement},t.openModal=function(e){r.disableOnMobile&&t.isMobileDevice()||(e.preventDefault(),t.saveLastDocElementFocused(),t.savePageScrollPosition(),t.saveScrollBehavior(),t.displayModal(e),t.hideModalFromScreenReader(!1),t.enablePageScrolling(!1),t.modalFocus(),t.triggerEvent(i,"open"))},t.displayModal=function(e){var o=t.getParentElement(e.target,"a");(i=t.getModal(o)).style.display="block"},t.modalFocus=function(){i.focusableChildren=Array.from(i.querySelectorAll('a[href], button:not([disabled]), [tabindex]:not([tabindex="-1"])')),i.focusableChildren[1].focus()},t.closeModal=function(e){e.preventDefault(),t.hideModal(),t.enablePageScrolling(!0),t.restorePageScrollPosition(),t.restoreScrollBehavior(),t.docRefocus(),t.triggerEvent(i,"close")},t.hideModal=function(){t.hideModalFromScreenReader(!0),t.isDefined(i)&&(i.style.display="none")},t.hideModalFromScreenReader=function(e){t.isDefined(i)&&i.setAttribute("aria-hidden",e)},t.enablePageScrolling=function(i){i?(o.classList.remove(t.prefix("-no-scroll")),e.classList.remove(t.prefix("-no-scroll"))):(o.classList.add(t.prefix("-no-scroll")),e.classList.add(t.prefix("-no-scroll")))},t.docRefocus=function(){n.focus()},t.openClient=function(e,o){var i="_blank";t.isDefaultEmailAppButton(e)&&(i="_self"),window.open(e.href,i),t.triggerEvent(e,"compose"),r.autoClose&&t.closeModal(o)},t.isDefaultEmailAppButton=function(e){return e.id==t.prefix("-button-4")},t.getParentElement=function(t,e){for(;null!==t;){if(t.tagName.toUpperCase()==e.toUpperCase())return t;t=t.parentNode}return null},t.triggerEvent=function(t,e){var o=new Event(e);t.dispatchEvent(o)},t.isMobileDevice=function(){var t,e=!1;return t=navigator.userAgent||navigator.vendor||window.opera,(/(android|bb\d+|meego).+mobile|avantgo|bada\/|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od)|iris|kindle|lge |maemo|midp|mmp|mobile.+firefox|netfront|opera m(ob|in)i|palm( os)?|phone|p(ixi|re)\/|plucker|pocket|psp|series(4|6)0|symbian|treo|up\.(browser|link)|vodafone|wap|windows ce|xda|xiino|android|ipad|playbook|silk/i.test(t)||/1207|6310|6590|3gso|4thp|50[1-6]i|770s|802s|a wa|abac|ac(er|oo|s\-)|ai(ko|rn)|al(av|ca|co)|amoi|an(ex|ny|yw)|aptu|ar(ch|go)|as(te|us)|attw|au(di|\-m|r |s )|avan|be(ck|ll|nq)|bi(lb|rd)|bl(ac|az)|br(e|v)w|bumb|bw\-(n|u)|c55\/|capi|ccwa|cdm\-|cell|chtm|cldc|cmd\-|co(mp|nd)|craw|da(it|ll|ng)|dbte|dc\-s|devi|dica|dmob|do(c|p)o|ds(12|\-d)|el(49|ai)|em(l2|ul)|er(ic|k0)|esl8|ez([4-7]0|os|wa|ze)|fetc|fly(\-|_)|g1 u|g560|gene|gf\-5|g\-mo|go(\.w|od)|gr(ad|un)|haie|hcit|hd\-(m|p|t)|hei\-|hi(pt|ta)|hp( i|ip)|hs\-c|ht(c(\-| |_|a|g|p|s|t)|tp)|hu(aw|tc)|i\-(20|go|ma)|i230|iac( |\-|\/)|ibro|idea|ig01|ikom|im1k|inno|ipaq|iris|ja(t|v)a|jbro|jemu|jigs|kddi|keji|kgt( |\/)|klon|kpt |kwc\-|kyo(c|k)|le(no|xi)|lg( g|\/(k|l|u)|50|54|\-[a-w])|libw|lynx|m1\-w|m3ga|m50\/|ma(te|ui|xo)|mc(01|21|ca)|m\-cr|me(rc|ri)|mi(o8|oa|ts)|mmef|mo(01|02|bi|de|do|t(\-| |o|v)|zz)|mt(50|p1|v )|mwbp|mywa|n10[0-2]|n20[2-3]|n30(0|2)|n50(0|2|5)|n7(0(0|1)|10)|ne((c|m)\-|on|tf|wf|wg|wt)|nok(6|i)|nzph|o2im|op(ti|wv)|oran|owg1|p800|pan(a|d|t)|pdxg|pg(13|\-([1-8]|c))|phil|pire|pl(ay|uc)|pn\-2|po(ck|rt|se)|prox|psio|pt\-g|qa\-a|qc(07|12|21|32|60|\-[2-7]|i\-)|qtek|r380|r600|raks|rim9|ro(ve|zo)|s55\/|sa(ge|ma|mm|ms|ny|va)|sc(01|h\-|oo|p\-)|sdk\/|se(c(\-|0|1)|47|mc|nd|ri)|sgh\-|shar|sie(\-|m)|sk\-0|sl(45|id)|sm(al|ar|b3|it|t5)|so(ft|ny)|sp(01|h\-|v\-|v )|sy(01|mb)|t2(18|50)|t6(00|10|18)|ta(gt|lk)|tcl\-|tdg\-|tel(i|m)|tim\-|t\-mo|to(pl|sh)|ts(70|m\-|m3|m5)|tx\-9|up(\.b|g1|si)|utst|v400|v750|veri|vi(rg|te)|vk(40|5[0-3]|\-v)|vm40|voda|vulc|vx(52|53|60|61|70|80|81|83|85|98)|w3c(\-| )|webc|whit|wi(g |nc|nw)|wmlb|wonu|x700|yas\-|your|zeto|zte\-/i.test(t.substr(0,4)))&&(e=!0),e},t.listenForEvents=function(){t.listenForClickOnLink(),t.listenForClickOnClient(),t.listenForClickOnCopy(),t.listenForClickOnClose(),t.listenForClickOnWindow(),t.listenForKeys()},t.listenForClickOnLink=function(){for(var e=document.getElementsByClassName(t.prefix()),o=0;o0&&(o[1]=e.replace(o[0]+"?","").trim()),o},t.getLinkField=function(e,o){var i=t.splitLink(e),n="",l=[],a=[];null!==i&&i.length>0&&(n=i[1]),null!==n&&n.length>0&&(l=(n=n.replace("%20&%20","%20%26%20")).split("&"));for(var r=0;r0&&(i=o[0]),decodeURIComponent(i)},t.getClassHideCopyUi=function(){return t.prefix("-is-hidden")},t.toggleHideCopyUi=function(e){var o=document.getElementById(t.prefix("-copy"));0==e.length?o.classList.add(t.getClassHideCopyUi()):o.classList.remove(t.getClassHideCopyUi())},t.toggleCopyButton=function(){button=document.getElementById(t.prefix("-button-copy")),buttonText=document.getElementById(t.prefix("-button-text-copy")),buttonText.innerHTML=r.buttonTextCopyAction,button.classList.add(t.prefix("-button-copy-clicked")),setTimeout(function(){buttonText.innerHTML=r.buttonTextCopy,button.classList.remove(t.prefix("-button-copy-clicked"))},600)},t.copy=function(e){e.preventDefault();var o=t.getParentElement(e.target,"button").getAttribute("data-copytargetid"),i=document.getElementById(o),n=document.createRange();n.selectNodeContents(i);var l=window.getSelection();l.removeAllRanges(),l.addRange(n),document.execCommand("copy"),t.triggerEvent(i,"copy"),t.toggleCopyButton()},t.isiOSDevice=function(){return navigator.userAgent.match(/ipad|iphone/i)},t.setOptions=function(e){if(e)var o=JSON.stringify(e);else o=t.getOptionsFromScriptTag();if(o&&o.trim().length>0)for(var i in o=JSON.parse(o),r)o.hasOwnProperty(i)&&(r[i]=t.sanitizeUserOption(i,o[i]))},t.sanitizeUserOption=function(e,o){return t.stringContains(e,"icon")?t.validateSvg(e,o):t.isString(o)?t.stripHtml(o):o},t.validateSvg=function(e,o){t.getSvg(e,o).then(function(i){if(!t.stringIsSvg(i.responseText))throw new Error(e+": "+o+" is not an SVG file.");if(t.stringHasScript(i.responseText))throw new Error(e+": "+o+" is an invalid SVG file.");r[e]=i.responseText}).catch(function(t){r[e]="buttonIconCopy"==e?a:l,console.log(t)})},t.loadSvg=function(t,e){return new Promise((t,o)=>{var i=new XMLHttpRequest;i.open("GET",e,!0),i.onload=function(e){200==i.status?t(i):o(i)},i.send()})},t.getSvg=async function(e,o){return await t.loadSvg(e,o)},t.isString=function(t){return"string"==typeof t},t.stripHtml=function(t){return t.replace(/(<([^>]+)>)/g,"")},t.stringContains=function(t,e){return-1!==t.toLowerCase().indexOf(e.toLowerCase())},t.stringIsSvg=function(t){return t.startsWith(" ',a=' ',r=new Object;r.linkClass="mailymaily",r.autoClose=!0,r.disableOnMobile=!0,r.title="Compose new email with",r.buttonText1="Gmail in browser",r.buttonText2="Outlook in browser",r.buttonText3="Yahoo in browser",r.buttonText4="Default email app",r.buttonIcon1=l,r.buttonIcon2=l,r.buttonIcon3=l,r.buttonIcon4=' ',r.buttonIconCopy=a,r.buttonTextCopy="Copy",r.buttonTextCopyAction="Copied!";var c=0,s="auto";t.buildStyleTag=function(){var e=document.createElement("style"),o=".mailymaily-modal{background-color:#000;background-color:rgba(0,0,0,.4);bottom:0;color:#303131;display:none;height:100%;left:0;margin:0;padding:0;position:fixed;right:0;top:0;width:100%;z-index:1000}.mailymaily-modal-content{-webkit-animation:mailymaily-appear .4s;animation:mailymaily-appear .4s;background-color:#f1f5f8;border-radius:8px;bottom:auto;-webkit-box-shadow:0 4px 8px 0 rgba(0,0,0,.2),0 6px 20px 0 rgba(0,0,0,.19);box-shadow:0 4px 8px 0 rgba(0,0,0,.2),0 6px 20px 0 rgba(0,0,0,.19);left:50%;max-height:calc(100% - 100px);overflow:auto;padding:0;position:fixed;right:-45%;top:50%;-webkit-transform:translate(-50%,-50%);transform:translate(-50%,-50%)}.mailymaily-modal-content:focus,.mailymaily-modal-content:hover{overflow-y:auto}@media only screen and (min-width:768px){.mailymaily-modal-content{right:auto}}.mailymaily-modal-head{-webkit-box-align:center;-ms-flex-align:center;align-items:center;background-color:#fff;clear:both;display:-webkit-box;display:-ms-flexbox;display:flex;min-width:0;padding:10px 20px}.mailymaily-modal-title{color:#303131;-webkit-box-flex:1;-ms-flex:1;flex:1;font-family:sans-serif;font-size:120%;font-weight:700;margin:0;overflow:hidden;padding:0;text-overflow:ellipsis;white-space:nowrap}.mailymaily-modal-close{color:#aaa;-webkit-box-flex:initial;-ms-flex:initial;flex:initial;font-size:38px;margin-left:20px;position:relative;text-align:right;text-decoration:none;top:-4px}.mailymaily-modal-close:focus,.mailymaily-modal-close:hover{color:#000;cursor:pointer;font-weight:700;outline:0}.mailymaily-modal-body{height:100%;padding:20px}.mailymaily-button{color:#333;text-decoration:none}.mailymaily-button:focus{outline:0}.mailymaily-button:focus .mailymaily-button-content{background-color:#555;color:#fff}.mailymaily-button-content{background-color:#fff;border:none;border-radius:8px;-webkit-box-shadow:0 2px 4px rgba(0,0,0,.18);box-shadow:0 2px 4px rgba(0,0,0,.18);margin-bottom:20px;overflow:hidden;padding:15px 20px;text-overflow:ellipsis;white-space:nowrap}.mailymaily-button-content:hover{background-color:#555;color:#fff}.mailymaily-button:last-child .mailymaily-button-content{margin-bottom:0}.mailymaily-button-icon{display:inline-block;font-weight:700;position:relative;top:4px}.mailymaily-button-icon svg{height:24px;width:24px}.mailymaily-button-text{display:inline-block;margin-left:5px;position:relative;top:-2px}.mailymaily-copy{border-radius:8px;-webkit-box-shadow:0 2px 4px rgba(0,0,0,.18);box-shadow:0 2px 4px rgba(0,0,0,.18);height:59px;margin-top:20px;position:relative}.mailymaily-button-copy{background-color:#fff;border:none;border-bottom-left-radius:8px;border-top-left-radius:8px;bottom:21px;color:#333;font-size:100%;height:100%;left:0;overflow:hidden;padding:15px 20px;position:absolute;text-overflow:ellipsis;top:0;white-space:nowrap;width:120px}.mailymaily-button-copy:focus,.mailymaily-button-copy:hover{background-color:#555;color:#fff;cursor:pointer;outline:0}.mailymaily-button-copy-clicked,.mailymaily-button-copy-clicked:focus,.mailymaily-button-copy-clicked:hover{background-color:#1f9d55;color:#fff}.mailymaily-button-copy-clicked .mailymaily-button-icon,.mailymaily-button-copy-clicked:focus .mailymaily-button-icon,.mailymaily-button-copy-clicked:hover .mailymaily-button-icon{display:none;visibility:hidden}.mailymaily-button-copy-clicked .mailymaily-button-text,.mailymaily-button-copy-clicked:focus .mailymaily-button-text,.mailymaily-button-copy-clicked:hover .mailymaily-button-text{color:#fff;top:2px}.mailymaily-email-address{background-color:#d8dcdf;border:none;border-radius:8px;-webkit-box-shadow:unset;box-shadow:unset;-webkit-box-sizing:border-box;box-sizing:border-box;color:#48494a;font-size:100%;height:100%;overflow:hidden;padding:20px 20px 20px 140px;text-overflow:ellipsis;white-space:nowrap;width:100%}.mailymaily-brand{color:#888;font-size:80%;margin-top:20px;text-align:center}.mailymaily-brand a{color:#888}.mailymaily-brand a:focus,.mailymaily-brand a:hover{font-weight:700;outline:0}.mailymaily-no-scroll{overflow:hidden;position:fixed;width:100%}.mailymaily-is-hidden{display:none;visibility:hidden}@-webkit-keyframes mailymaily-appear{0%{opacity:0;-webkit-transform:translate(-50%,-50%) scale(0,0);transform:translate(-50%,-50%) scale(0,0)}100%{opacity:1;-webkit-transform:translate(-50%,-50%) scale(1,1);transform:translate(-50%,-50%) scale(1,1)}}@keyframes mailymaily-appear{0%{opacity:0;-webkit-transform:translate(-50%,-50%) scale(0,0);transform:translate(-50%,-50%) scale(0,0)}100%{opacity:1;-webkit-transform:translate(-50%,-50%) scale(1,1);transform:translate(-50%,-50%) scale(1,1)}}";return o=o.replace(/mailymaily/g,t.prefix()),e.setAttribute("id",t.prefix("-styles")),e.setAttribute("type","text/css"),e.styleSheet?e.styleSheet.cssText=o:e.appendChild(document.createTextNode(o)),e},t.embedStyleTag=function(){if(!t.styleTagExists()){var e=document.head.firstChild;document.head.insertBefore(t.buildStyleTag(),e)}},t.styleTagExists=function(){return!!document.getElementById(t.prefix("-styles"))},t.buildModal=function(){var e=document.createElement("div"),o=``;return o=o.replace(/mailymaily/g,t.prefix()),e.setAttribute("id",t.prefix("-modal")),e.setAttribute("class",t.prefix("-modal")),e.setAttribute("style","display: none;"),e.setAttribute("aria-hidden",!0),e.innerHTML=o,e},t.embedModal=function(){if(!t.modalExists()){var e=t.buildModal(),o=document.body.firstChild;document.body.insertBefore(e,o)}},t.modalExists=function(){return!!document.getElementById(t.prefix("-modal"))},t.getModal=function(e){return t.hydrateModal(e),document.getElementById(t.prefix("-modal"))},t.hydrateModal=function(e){var o=t.getEmail(e),i=t.getLinkField(e,"subject"),n=t.getLinkField(e,"cc"),l=t.getLinkField(e,"bcc"),a=t.getLinkField(e,"body");document.getElementById(t.prefix("-button-1")).href="https://mail.google.com/mail/?view=cm&fs=1&to="+o+"&su="+i+"&cc="+n+"&bcc="+l+"&body="+a,document.getElementById(t.prefix("-button-2")).href=`https://outlook.office.com/owa/?path=/mail/action/compose&to=${o}&subject=${i}&body=${a}`,document.getElementById(t.prefix("-button-3")).href=`https://compose.mail.yahoo.com/?to=${o}&subject=${i}&cc=${n}&bcc=${l}&body=${a}`,document.getElementById(t.prefix("-button-4")).href=`mailto:${o}?subject=${i}&cc=${n}&bcc=${l}&body=${a}`,document.getElementById(t.prefix("-email-address")).innerHTML=o,document.getElementById(t.prefix("-button-icon-1")).innerHTML=r.buttonIcon1,document.getElementById(t.prefix("-button-icon-2")).innerHTML=r.buttonIcon2,document.getElementById(t.prefix("-button-icon-3")).innerHTML=r.buttonIcon3,document.getElementById(t.prefix("-button-icon-4")).innerHTML=r.buttonIcon4,document.getElementById(t.prefix("-button-icon-copy")).innerHTML=r.buttonIconCopy,t.toggleHideCopyUi(o)},t.savePageScrollPosition=function(){c=window.pageYOffset,o.style.top=-c+"px"},t.restorePageScrollPosition=function(){window.scrollTo(0,c),o.style.top=0},t.saveScrollBehavior=function(){s=e.style.scrollBehavior,e.style.scrollBehavior="auto"},t.restoreScrollBehavior=function(){e.style.scrollBehavior=s},t.saveLastDocElementFocused=function(){n=document.activeElement},t.openModal=function(e){r.disableOnMobile&&t.isMobileDevice()||(e.preventDefault(),t.saveLastDocElementFocused(),t.savePageScrollPosition(),t.saveScrollBehavior(),t.displayModal(e),t.hideModalFromScreenReader(!1),t.enablePageScrolling(!1),t.modalFocus(),t.triggerEvent(i,"open"))},t.displayModal=function(e){var o=t.getParentElement(e.target,"a");(i=t.getModal(o)).style.display="block"},t.modalFocus=function(){i.focusableChildren=Array.from(i.querySelectorAll('a[href], button:not([disabled]), [tabindex]:not([tabindex="-1"])')),i.focusableChildren[1].focus()},t.closeModal=function(e){e.preventDefault(),t.hideModal(),t.enablePageScrolling(!0),t.restorePageScrollPosition(),t.restoreScrollBehavior(),t.docRefocus(),t.triggerEvent(i,"close")},t.hideModal=function(){t.hideModalFromScreenReader(!0),t.isDefined(i)&&(i.style.display="none")},t.hideModalFromScreenReader=function(e){t.isDefined(i)&&i.setAttribute("aria-hidden",e)},t.enablePageScrolling=function(i){i?(o.classList.remove(t.prefix("-no-scroll")),e.classList.remove(t.prefix("-no-scroll"))):(o.classList.add(t.prefix("-no-scroll")),e.classList.add(t.prefix("-no-scroll")))},t.docRefocus=function(){n.focus()},t.openClient=function(e,o){var i="_blank";t.isDefaultEmailAppButton(e)&&(i="_self"),window.open(e.href,i),t.triggerEvent(e,"compose"),r.autoClose&&t.closeModal(o)},t.isDefaultEmailAppButton=function(e){return e.id==t.prefix("-button-4")},t.getParentElement=function(t,e){for(;null!==t;){if(t.tagName.toUpperCase()==e.toUpperCase())return t;t=t.parentNode}return null},t.triggerEvent=function(t,e){var o=new Event(e);t.dispatchEvent(o)},t.isMobileDevice=function(){var t,e=!1;return t=navigator.userAgent||navigator.vendor||window.opera,(/(android|bb\d+|meego).+mobile|avantgo|bada\/|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od)|iris|kindle|lge |maemo|midp|mmp|mobile.+firefox|netfront|opera m(ob|in)i|palm( os)?|phone|p(ixi|re)\/|plucker|pocket|psp|series(4|6)0|symbian|treo|up\.(browser|link)|vodafone|wap|windows ce|xda|xiino|android|ipad|playbook|silk/i.test(t)||/1207|6310|6590|3gso|4thp|50[1-6]i|770s|802s|a wa|abac|ac(er|oo|s\-)|ai(ko|rn)|al(av|ca|co)|amoi|an(ex|ny|yw)|aptu|ar(ch|go)|as(te|us)|attw|au(di|\-m|r |s )|avan|be(ck|ll|nq)|bi(lb|rd)|bl(ac|az)|br(e|v)w|bumb|bw\-(n|u)|c55\/|capi|ccwa|cdm\-|cell|chtm|cldc|cmd\-|co(mp|nd)|craw|da(it|ll|ng)|dbte|dc\-s|devi|dica|dmob|do(c|p)o|ds(12|\-d)|el(49|ai)|em(l2|ul)|er(ic|k0)|esl8|ez([4-7]0|os|wa|ze)|fetc|fly(\-|_)|g1 u|g560|gene|gf\-5|g\-mo|go(\.w|od)|gr(ad|un)|haie|hcit|hd\-(m|p|t)|hei\-|hi(pt|ta)|hp( i|ip)|hs\-c|ht(c(\-| |_|a|g|p|s|t)|tp)|hu(aw|tc)|i\-(20|go|ma)|i230|iac( |\-|\/)|ibro|idea|ig01|ikom|im1k|inno|ipaq|iris|ja(t|v)a|jbro|jemu|jigs|kddi|keji|kgt( |\/)|klon|kpt |kwc\-|kyo(c|k)|le(no|xi)|lg( g|\/(k|l|u)|50|54|\-[a-w])|libw|lynx|m1\-w|m3ga|m50\/|ma(te|ui|xo)|mc(01|21|ca)|m\-cr|me(rc|ri)|mi(o8|oa|ts)|mmef|mo(01|02|bi|de|do|t(\-| |o|v)|zz)|mt(50|p1|v )|mwbp|mywa|n10[0-2]|n20[2-3]|n30(0|2)|n50(0|2|5)|n7(0(0|1)|10)|ne((c|m)\-|on|tf|wf|wg|wt)|nok(6|i)|nzph|o2im|op(ti|wv)|oran|owg1|p800|pan(a|d|t)|pdxg|pg(13|\-([1-8]|c))|phil|pire|pl(ay|uc)|pn\-2|po(ck|rt|se)|prox|psio|pt\-g|qa\-a|qc(07|12|21|32|60|\-[2-7]|i\-)|qtek|r380|r600|raks|rim9|ro(ve|zo)|s55\/|sa(ge|ma|mm|ms|ny|va)|sc(01|h\-|oo|p\-)|sdk\/|se(c(\-|0|1)|47|mc|nd|ri)|sgh\-|shar|sie(\-|m)|sk\-0|sl(45|id)|sm(al|ar|b3|it|t5)|so(ft|ny)|sp(01|h\-|v\-|v )|sy(01|mb)|t2(18|50)|t6(00|10|18)|ta(gt|lk)|tcl\-|tdg\-|tel(i|m)|tim\-|t\-mo|to(pl|sh)|ts(70|m\-|m3|m5)|tx\-9|up(\.b|g1|si)|utst|v400|v750|veri|vi(rg|te)|vk(40|5[0-3]|\-v)|vm40|voda|vulc|vx(52|53|60|61|70|80|81|83|85|98)|w3c(\-| )|webc|whit|wi(g |nc|nw)|wmlb|wonu|x700|yas\-|your|zeto|zte\-/i.test(t.substr(0,4)))&&(e=!0),e},t.listenForEvents=function(){t.listenForClickOnLink(),t.listenForClickOnClient(),t.listenForClickOnCopy(),t.listenForClickOnClose(),t.listenForClickOnWindow(),t.listenForKeys()},t.listenForClickOnLink=function(){for(var e=document.getElementsByClassName(t.prefix()),o=0;o0&&(o[1]=e.replace(o[0]+"?","").trim()),o},t.getLinkField=function(e,o){var i=t.splitLink(e),n="",l=[],a=[];null!==i&&i.length>0&&(n=i[1]),null!==n&&n.length>0&&(l=(n=n.replace("%20&%20","%20%26%20")).split("&"));for(var r=0;r0&&(i=o[0]),decodeURIComponent(i)},t.getClassHideCopyUi=function(){return t.prefix("-is-hidden")},t.toggleHideCopyUi=function(e){var o=document.getElementById(t.prefix("-copy"));0==e.length?o.classList.add(t.getClassHideCopyUi()):o.classList.remove(t.getClassHideCopyUi())},t.toggleCopyButton=function(){button=document.getElementById(t.prefix("-button-copy")),buttonText=document.getElementById(t.prefix("-button-text-copy")),buttonText.innerHTML=r.buttonTextCopyAction,button.classList.add(t.prefix("-button-copy-clicked")),setTimeout(function(){buttonText.innerHTML=r.buttonTextCopy,button.classList.remove(t.prefix("-button-copy-clicked"))},600)},t.copy=function(e){e.preventDefault();var o=t.getParentElement(e.target,"button").getAttribute("data-copytargetid"),i=document.getElementById(o),n=document.createRange();n.selectNodeContents(i);var l=window.getSelection();l.removeAllRanges(),l.addRange(n),document.execCommand("copy"),t.triggerEvent(i,"copy"),t.toggleCopyButton()},t.isiOSDevice=function(){return navigator.userAgent.match(/ipad|iphone/i)},t.setOptions=function(e){if(e)var o=JSON.stringify(e);else o=t.getOptionsFromScriptTag();if(o&&o.trim().length>0)for(var i in o=JSON.parse(o),r)o.hasOwnProperty(i)&&(r[i]=t.sanitizeUserOption(i,o[i]))},t.sanitizeUserOption=function(e,o){return t.stringContains(e,"icon")?t.validateSvg(e,o):t.isString(o)?t.stripHtml(o):o},t.validateSvg=function(e,o){t.getSvg(e,o).then(function(i){if(!t.stringIsSvg(i.responseText))throw new Error(e+": "+o+" is not an SVG file.");if(t.stringHasScript(i.responseText))throw new Error(e+": "+o+" is an invalid SVG file.");r[e]=i.responseText}).catch(function(t){r[e]="buttonIconCopy"==e?a:l,console.log(t)})},t.loadSvg=function(t,e){return new Promise((t,o)=>{var i=new XMLHttpRequest;i.open("GET",e,!0),i.onload=function(e){200==i.status?t(i):o(i)},i.send()})},t.getSvg=async function(e,o){return await t.loadSvg(e,o)},t.isString=function(t){return"string"==typeof t},t.stripHtml=function(t){return t.replace(/(<([^>]+)>)/g,"")},t.stringContains=function(t,e){return-1!==t.toLowerCase().indexOf(e.toLowerCase())},t.stringIsSvg=function(t){return t.startsWith(" src('./src/js/mailymaily.js').pipe(minify({ noSource: true })).pipe(dest('./dist')); +exports.default = series(parallel(html, css), js); diff --git a/package.json b/package.json index 980b47a..4423f69 100644 --- a/package.json +++ b/package.json @@ -4,10 +4,6 @@ "version": "1.0.0", "license": "MIT", "devDependencies": { - "@babel/core": "^7.5.5", - "@babel/plugin-transform-regenerator": "^7.4.5", - "@babel/preset-env": "^7.5.5", - "fs-extra": "^7.0.1", "gulp": "^4.0.2", "gulp-autoprefixer": "^6.1.0", "gulp-clean-css": "^4.2.0", @@ -16,11 +12,8 @@ "gulp-minify": "^3.1.0", "gulp-rename": "^1.4.0", "gulp-sass": "^4.0.2", - "gulp-util": "^3.0.8", - "gulp-watch": "^5.0.1", "node-sass": "^4.12.0", - "prettier": "1.15.3", - "vue": "^2.6.10" + "vue": "^2.6.12" }, "scripts": { "build": "gulp" diff --git a/src/js/mailymaily.js b/src/js/mailymaily.js index 9e6baef..bc94e80 100644 --- a/src/js/mailymaily.js +++ b/src/js/mailymaily.js @@ -1,562 +1,510 @@ -/** - * mailymaily - A simple way to enhance your mailto links with a convenient user interface. - * - * @link https://mailymaily.com - * @author Mario Rodriguez - https://twitter.com/mariordev - * @license MIT - * - * mailymaily is a library that enhances your mailto links with a convenient user interface. - * It gives your site visitors the flexibility to compose a new email message using a - * browser-based email client or their default local email application. - */ - -/** - * Let's not step on anybody else's toes. - */ +// Let's not step on anybody else's toes. var mailymailyApp = mailymailyApp || {}; (function(app) { - /** + /** * The html element. * @type {Element} */ - var html = document.getElementsByTagName('html')[0]; + var html = document.getElementsByTagName('html')[0]; - /** + /** * The body element. * @type {Element} */ - var body = document.getElementsByTagName('body')[0]; + var body = document.getElementsByTagName('body')[0]; - /** + /** * The active mailymaily modal. * @type {Element} */ - var modal = null; + var modal = null; - /** + /** * List of focusable elements within modal. * @type {String} */ - var focusable = 'a[href], button:not([disabled]), [tabindex]:not([tabindex="-1"])'; + var focusable = 'a[href], button:not([disabled]), [tabindex]:not([tabindex="-1"])'; - /** + /** * The last document element to have focus before the modal was opened. * Focus is to be set back on this element after the modal is closed. * @type {Element} */ - var lastDocElementFocused = null; + var lastDocElementFocused = null; - /** + /** * The default svg icon for email client buttons. * @type {String} */ - var worldSvg = ` `; + var worldSvg = ` `; - /** + /** * The default svg icon for default email app button. * @type {String} */ - var uiSvg = ` `; + var uiSvg = ` `; - /** + /** * The default svg icon for copy button. * @type {String} */ - var clipboardSvg = ` `; + var clipboardSvg = ` `; - /** + /** * User options to change mailymaily's behavior and/or appearance. * @type {Object} */ - var options = new Object(); + var options = new Object(); - /** + /** * Allows for a custom class to namespace css classes. * @type {String} */ - options.linkClass = 'mailymaily'; + options.linkClass = 'mailymaily'; - /** + /** * When set to true, the modal is closed automatically when email client is clicked. * @type {Boolean} */ - options.autoClose = true; + options.autoClose = true; - /** + /** * When set to true, the modal is not displayed on mobile devices, and the local email app is used automatically. * @type {Boolean} */ - options.disableOnMobile = true; + options.disableOnMobile = true; - /** + /** * The modal title. * @type {String} */ - options.title = 'Compose new email with'; + options.title = 'Compose new email with'; - /** + /** * Text for button 1. * @type {String} */ - options.buttonText1 = 'Gmail in browser'; + options.buttonText1 = 'Gmail in browser'; - /** + /** * Text for button 2. * @type {String} */ - options.buttonText2 = 'Outlook in browser'; + options.buttonText2 = 'Outlook in browser'; - /** + /** * Text for button 3. * @type {String} */ - options.buttonText3 = 'Yahoo in browser'; + options.buttonText3 = 'Yahoo in browser'; - /** + /** * Text for button 4. * @type {String} */ - options.buttonText4 = 'Default email app'; + options.buttonText4 = 'Default email app'; - /** + /** * URL of svg file used as icon for button 1. * @type {String} */ - options.buttonIcon1 = worldSvg; + options.buttonIcon1 = worldSvg; - /** + /** * URL of svg file used as icon for button 2. * @type {String} */ - options.buttonIcon2 = worldSvg; + options.buttonIcon2 = worldSvg; - /** + /** * URL of svg file used as icon for button 3. * @type {String} */ - options.buttonIcon3 = worldSvg; + options.buttonIcon3 = worldSvg; - /** + /** * URL of svg file used as icon for button 4. * @type {String} */ - options.buttonIcon4 = uiSvg; + options.buttonIcon4 = uiSvg; - /** + /** * URL of svg file used as icon for Copy button. * @type {String} */ - options.buttonIconCopy = clipboardSvg; + options.buttonIconCopy = clipboardSvg; - /** + /** * Text for Copy button. * @type {String} */ - options.buttonTextCopy = 'Copy'; + options.buttonTextCopy = 'Copy'; - /** + /** * Text for Copy button when clicked. * @type {String} */ - options.buttonTextCopyAction = 'Copied!'; + options.buttonTextCopyAction = 'Copied!'; - /** + /** * Keep track of the page's scroll position. * @type {Number} */ - var scrollPosition = 0; + var scrollPosition = 0; - /** + /** * Keep track of the page's original scroll behavior. * @type {String} */ - var scrollBehavior = 'auto'; + var scrollBehavior = 'auto'; - /** + /** * Build a style tag with default styling to be embedded on the page. * * @return {String} The style tag markup. */ - app.buildStyleTag = function() { - var styleTag = document.createElement('style'); - var css = `.mailymaily-modal{background-color:#000;background-color:rgba(0,0,0,.4);bottom:0;color:#303131;display:none;height:100%;left:0;margin:0;padding:0;position:fixed;right:0;top:0;width:100%;z-index:1000}.mailymaily-modal-content{-webkit-animation:mailymaily-appear .4s;animation:mailymaily-appear .4s;background-color:#f1f5f8;border-radius:8px;bottom:auto;-webkit-box-shadow:0 4px 8px 0 rgba(0,0,0,.2),0 6px 20px 0 rgba(0,0,0,.19);box-shadow:0 4px 8px 0 rgba(0,0,0,.2),0 6px 20px 0 rgba(0,0,0,.19);left:50%;max-height:calc(100% - 100px);overflow:auto;padding:0;position:fixed;right:-45%;top:50%;-webkit-transform:translate(-50%,-50%);transform:translate(-50%,-50%)}.mailymaily-modal-content:focus,.mailymaily-modal-content:hover{overflow-y:auto}@media only screen and (min-width:768px){.mailymaily-modal-content{right:auto}}.mailymaily-modal-head{-webkit-box-align:center;-ms-flex-align:center;align-items:center;background-color:#fff;clear:both;display:-webkit-box;display:-ms-flexbox;display:flex;min-width:0;padding:10px 20px}.mailymaily-modal-title{color:#303131;-webkit-box-flex:1;-ms-flex:1;flex:1;font-family:sans-serif;font-size:120%;font-weight:700;margin:0;overflow:hidden;padding:0;text-overflow:ellipsis;white-space:nowrap}.mailymaily-modal-close{color:#aaa;-webkit-box-flex:initial;-ms-flex:initial;flex:initial;font-size:38px;margin-left:20px;position:relative;text-align:right;text-decoration:none;top:-4px}.mailymaily-modal-close:focus,.mailymaily-modal-close:hover{color:#000;cursor:pointer;font-weight:700;outline:0}.mailymaily-modal-body{height:100%;padding:20px}.mailymaily-button{color:#333;text-decoration:none}.mailymaily-button:focus{outline:0}.mailymaily-button:focus .mailymaily-button-content{background-color:#555;color:#fff}.mailymaily-button-content{background-color:#fff;border:none;border-radius:8px;-webkit-box-shadow:0 2px 4px rgba(0,0,0,.18);box-shadow:0 2px 4px rgba(0,0,0,.18);margin-bottom:20px;overflow:hidden;padding:15px 20px;text-overflow:ellipsis;white-space:nowrap}.mailymaily-button-content:hover{background-color:#555;color:#fff}.mailymaily-button:last-child .mailymaily-button-content{margin-bottom:0}.mailymaily-button-icon{display:inline-block;font-weight:700;position:relative;top:4px}.mailymaily-button-icon svg{height:24px;width:24px}.mailymaily-button-text{display:inline-block;margin-left:5px;position:relative;top:-2px}.mailymaily-copy{border-radius:8px;-webkit-box-shadow:0 2px 4px rgba(0,0,0,.18);box-shadow:0 2px 4px rgba(0,0,0,.18);height:59px;margin-top:20px;position:relative}.mailymaily-button-copy{background-color:#fff;border:none;border-bottom-left-radius:8px;border-top-left-radius:8px;bottom:21px;color:#333;font-size:100%;height:100%;left:0;overflow:hidden;padding:15px 20px;position:absolute;text-overflow:ellipsis;top:0;white-space:nowrap;width:120px}.mailymaily-button-copy:focus,.mailymaily-button-copy:hover{background-color:#555;color:#fff;cursor:pointer;outline:0}.mailymaily-button-copy-clicked,.mailymaily-button-copy-clicked:focus,.mailymaily-button-copy-clicked:hover{background-color:#1f9d55;color:#fff}.mailymaily-button-copy-clicked .mailymaily-button-icon,.mailymaily-button-copy-clicked:focus .mailymaily-button-icon,.mailymaily-button-copy-clicked:hover .mailymaily-button-icon{display:none;visibility:hidden}.mailymaily-button-copy-clicked .mailymaily-button-text,.mailymaily-button-copy-clicked:focus .mailymaily-button-text,.mailymaily-button-copy-clicked:hover .mailymaily-button-text{color:#fff;top:2px}.mailymaily-email-address{background-color:#d8dcdf;border:none;border-radius:8px;-webkit-box-shadow:unset;box-shadow:unset;-webkit-box-sizing:border-box;box-sizing:border-box;color:#48494a;font-size:100%;height:100%;overflow:hidden;padding:20px 20px 20px 140px;text-overflow:ellipsis;white-space:nowrap;width:100%}.mailymaily-brand{color:#888;font-size:80%;margin-top:20px;text-align:center}.mailymaily-brand a{color:#888}.mailymaily-brand a:focus,.mailymaily-brand a:hover{font-weight:700;outline:0}.mailymaily-no-scroll{overflow:hidden;position:fixed;width:100%}.mailymaily-is-hidden{display:none;visibility:hidden}@-webkit-keyframes mailymaily-appear{0%{opacity:0;-webkit-transform:translate(-50%,-50%) scale(0,0);transform:translate(-50%,-50%) scale(0,0)}100%{opacity:1;-webkit-transform:translate(-50%,-50%) scale(1,1);transform:translate(-50%,-50%) scale(1,1)}}@keyframes mailymaily-appear{0%{opacity:0;-webkit-transform:translate(-50%,-50%) scale(0,0);transform:translate(-50%,-50%) scale(0,0)}100%{opacity:1;-webkit-transform:translate(-50%,-50%) scale(1,1);transform:translate(-50%,-50%) scale(1,1)}}`; - css = css.replace(/mailymaily/g, app.prefix()); + app.buildStyleTag = function() { + var styleTag = document.createElement('style'); + var css = `.mailymaily-modal{background-color:#000;background-color:rgba(0,0,0,.4);bottom:0;color:#303131;display:none;height:100%;left:0;margin:0;padding:0;position:fixed;right:0;top:0;width:100%;z-index:1000}.mailymaily-modal-content{-webkit-animation:mailymaily-appear .4s;animation:mailymaily-appear .4s;background-color:#f1f5f8;border-radius:8px;bottom:auto;-webkit-box-shadow:0 4px 8px 0 rgba(0,0,0,.2),0 6px 20px 0 rgba(0,0,0,.19);box-shadow:0 4px 8px 0 rgba(0,0,0,.2),0 6px 20px 0 rgba(0,0,0,.19);left:50%;max-height:calc(100% - 100px);overflow:auto;padding:0;position:fixed;right:-45%;top:50%;-webkit-transform:translate(-50%,-50%);transform:translate(-50%,-50%)}.mailymaily-modal-content:focus,.mailymaily-modal-content:hover{overflow-y:auto}@media only screen and (min-width:768px){.mailymaily-modal-content{right:auto}}.mailymaily-modal-head{-webkit-box-align:center;-ms-flex-align:center;align-items:center;background-color:#fff;clear:both;display:-webkit-box;display:-ms-flexbox;display:flex;min-width:0;padding:10px 20px}.mailymaily-modal-title{color:#303131;-webkit-box-flex:1;-ms-flex:1;flex:1;font-family:sans-serif;font-size:120%;font-weight:700;margin:0;overflow:hidden;padding:0;text-overflow:ellipsis;white-space:nowrap}.mailymaily-modal-close{color:#aaa;-webkit-box-flex:initial;-ms-flex:initial;flex:initial;font-size:38px;margin-left:20px;position:relative;text-align:right;text-decoration:none;top:-4px}.mailymaily-modal-close:focus,.mailymaily-modal-close:hover{color:#000;cursor:pointer;font-weight:700;outline:0}.mailymaily-modal-body{height:100%;padding:20px}.mailymaily-button{color:#333;text-decoration:none}.mailymaily-button:focus{outline:0}.mailymaily-button:focus .mailymaily-button-content{background-color:#555;color:#fff}.mailymaily-button-content{background-color:#fff;border:none;border-radius:8px;-webkit-box-shadow:0 2px 4px rgba(0,0,0,.18);box-shadow:0 2px 4px rgba(0,0,0,.18);margin-bottom:20px;overflow:hidden;padding:15px 20px;text-overflow:ellipsis;white-space:nowrap}.mailymaily-button-content:hover{background-color:#555;color:#fff}.mailymaily-button:last-child .mailymaily-button-content{margin-bottom:0}.mailymaily-button-icon{display:inline-block;font-weight:700;position:relative;top:4px}.mailymaily-button-icon svg{height:24px;width:24px}.mailymaily-button-text{display:inline-block;margin-left:5px;position:relative;top:-2px}.mailymaily-copy{border-radius:8px;-webkit-box-shadow:0 2px 4px rgba(0,0,0,.18);box-shadow:0 2px 4px rgba(0,0,0,.18);height:59px;margin-top:20px;position:relative}.mailymaily-button-copy{background-color:#fff;border:none;border-bottom-left-radius:8px;border-top-left-radius:8px;bottom:21px;color:#333;font-size:100%;height:100%;left:0;overflow:hidden;padding:15px 20px;position:absolute;text-overflow:ellipsis;top:0;white-space:nowrap;width:120px}.mailymaily-button-copy:focus,.mailymaily-button-copy:hover{background-color:#555;color:#fff;cursor:pointer;outline:0}.mailymaily-button-copy-clicked,.mailymaily-button-copy-clicked:focus,.mailymaily-button-copy-clicked:hover{background-color:#1f9d55;color:#fff}.mailymaily-button-copy-clicked .mailymaily-button-icon,.mailymaily-button-copy-clicked:focus .mailymaily-button-icon,.mailymaily-button-copy-clicked:hover .mailymaily-button-icon{display:none;visibility:hidden}.mailymaily-button-copy-clicked .mailymaily-button-text,.mailymaily-button-copy-clicked:focus .mailymaily-button-text,.mailymaily-button-copy-clicked:hover .mailymaily-button-text{color:#fff;top:2px}.mailymaily-email-address{background-color:#d8dcdf;border:none;border-radius:8px;-webkit-box-shadow:unset;box-shadow:unset;-webkit-box-sizing:border-box;box-sizing:border-box;color:#48494a;font-size:100%;height:100%;overflow:hidden;padding:20px 20px 20px 140px;text-overflow:ellipsis;white-space:nowrap;width:100%}.mailymaily-brand{color:#888;font-size:80%;margin-top:20px;text-align:center}.mailymaily-brand a{color:#888}.mailymaily-brand a:focus,.mailymaily-brand a:hover{font-weight:700;outline:0}.mailymaily-no-scroll{overflow:hidden;position:fixed;width:100%}.mailymaily-is-hidden{display:none;visibility:hidden}@-webkit-keyframes mailymaily-appear{0%{opacity:0;-webkit-transform:translate(-50%,-50%) scale(0,0);transform:translate(-50%,-50%) scale(0,0)}100%{opacity:1;-webkit-transform:translate(-50%,-50%) scale(1,1);transform:translate(-50%,-50%) scale(1,1)}}@keyframes mailymaily-appear{0%{opacity:0;-webkit-transform:translate(-50%,-50%) scale(0,0);transform:translate(-50%,-50%) scale(0,0)}100%{opacity:1;-webkit-transform:translate(-50%,-50%) scale(1,1);transform:translate(-50%,-50%) scale(1,1)}}`; + css = css.replace(/mailymaily/g, app.prefix()); - styleTag.setAttribute('id', app.prefix('-styles')); - styleTag.setAttribute('type', 'text/css'); + styleTag.setAttribute('id', app.prefix('-styles')); + styleTag.setAttribute('type', 'text/css'); - if (styleTag.styleSheet) { - // Required for IE8 and below. - styleTag.styleSheet.cssText = css; - } else { - styleTag.appendChild(document.createTextNode(css)); - } + if (styleTag.styleSheet) { + // Required for IE8 and below. + styleTag.styleSheet.cssText = css; + } else { + styleTag.appendChild(document.createTextNode(css)); + } - return styleTag; - }; + return styleTag; + }; - /** + /** * Embed style tag on the page. */ - app.embedStyleTag = function() { - if (app.styleTagExists()) { - return; - } + app.embedStyleTag = function() { + if (app.styleTagExists()) { + return; + } - var firstHeadChild = document.head.firstChild; + var firstHeadChild = document.head.firstChild; - document.head.insertBefore(app.buildStyleTag(), firstHeadChild); - }; + document.head.insertBefore(app.buildStyleTag(), firstHeadChild); + }; - /** + /** * Check if style tag has already been embedded on the page. * * @return {Boolean} True if style tag is already embedded. */ - app.styleTagExists = function() { - if (document.getElementById(app.prefix('-styles'))) { - return true; - } + app.styleTagExists = function() { + if (document.getElementById(app.prefix('-styles'))) { + return true; + } - return false; - }; + return false; + }; - /** + /** * Build the modal markup. * * @return {String} The modal markup. */ - app.buildModal = function() { - var modal = document.createElement('div'); + app.buildModal = function() { + var modal = document.createElement('div'); - var markup = ``; + var markup = ``; - markup = markup.replace(/mailymaily/g, app.prefix()); + markup = markup.replace(/mailymaily/g, app.prefix()); - modal.setAttribute('id', app.prefix('-modal')); - modal.setAttribute('class', app.prefix('-modal')); - modal.setAttribute('style', 'display: none;'); - modal.setAttribute('aria-hidden', true); - modal.innerHTML = markup; + modal.setAttribute('id', app.prefix('-modal')); + modal.setAttribute('class', app.prefix('-modal')); + modal.setAttribute('style', 'display: none;'); + modal.setAttribute('aria-hidden', true); + modal.innerHTML = markup; - return modal; - }; + return modal; + }; - /** + /** * Embed modal on the page. */ - app.embedModal = function() { - if (app.modalExists()) { - return; - } + app.embedModal = function() { + if (app.modalExists()) { + return; + } - var modal = app.buildModal(); - var firstBodyChild = document.body.firstChild; + var modal = app.buildModal(); + var firstBodyChild = document.body.firstChild; - document.body.insertBefore(modal, firstBodyChild); - }; + document.body.insertBefore(modal, firstBodyChild); + }; - /** + /** * Check if modal markup has already been embedded on page. * * @return {Boolean} True if modal markup ia already embedded. */ - app.modalExists = function() { - if (document.getElementById(app.prefix('-modal'))) { - return true; - } + app.modalExists = function() { + if (document.getElementById(app.prefix('-modal'))) { + return true; + } - return false; - }; + return false; + }; - /** + /** * Get modal populated with data from the given link. * * @param {Element} link The link that was clicked. * @return {Element} The modal associated with the given link. */ - app.getModal = function(link) { - app.hydrateModal(link); + app.getModal = function(link) { + app.hydrateModal(link); - return document.getElementById(app.prefix('-modal')); - }; + return document.getElementById(app.prefix('-modal')); + }; - /** + /** * Populate current modal with data from the link that was clicked. * * @param {Element} link The link that was clicked. */ - app.hydrateModal = function(link) { - var email = app.getEmail(link); - var subject = app.getLinkField(link, 'subject'); - var cc = app.getLinkField(link, 'cc'); - var bcc = app.getLinkField(link, 'bcc'); - var body = app.getLinkField(link, 'body'); + app.hydrateModal = function(link) { + var email = app.getEmail(link); + var subject = app.getLinkField(link, 'subject'); + var cc = app.getLinkField(link, 'cc'); + var bcc = app.getLinkField(link, 'bcc'); + var body = app.getLinkField(link, 'body'); - var gmail = document.getElementById(app.prefix('-button-1')); - gmail.href = - 'https://mail.google.com/mail/?view=cm&fs=1&to=' + - email + - '&su=' + - subject + - '&cc=' + - cc + - '&bcc=' + - bcc + - '&body=' + - body; + var gmail = document.getElementById(app.prefix('-button-1')); + gmail.href = + 'https://mail.google.com/mail/?view=cm&fs=1&to=' + + email + + '&su=' + + subject + + '&cc=' + + cc + + '&bcc=' + + bcc + + '&body=' + + body; - var outlook = document.getElementById(app.prefix('-button-2')); - outlook.href = - 'https://outlook.office.com/owa/?path=/mail/action/compose&to=' + - email + - '&subject=' + - subject + - '&body=' + - body; + var outlook = document.getElementById(app.prefix('-button-2')); + outlook.href = `https://outlook.office.com/owa/?path=/mail/action/compose&to=${email}&subject=${subject}&body=${body}`; - var yahoo = document.getElementById(app.prefix('-button-3')); - yahoo.href = - 'https://compose.mail.yahoo.com/?to=' + - email + - '&subject=' + - subject + - '&cc=' + - cc + - '&bcc=' + - bcc + - '&body=' + - body; + var yahoo = document.getElementById(app.prefix('-button-3')); + yahoo.href = `https://compose.mail.yahoo.com/?to=${email}&subject=${subject}&cc=${cc}&bcc=${bcc}&body=${body}`; - var defaultApp = document.getElementById(app.prefix('-button-4')); - defaultApp.href = 'mailto:' + email + '?subject=' + subject + '&cc=' + cc + '&bcc=' + bcc + '&body=' + body; + var defaultApp = document.getElementById(app.prefix('-button-4')); + defaultApp.href = `mailto:${email}?subject=${subject}&cc=${cc}&bcc=${bcc}&body=${body}`; - var emailField = document.getElementById(app.prefix('-email-address')); - emailField.innerHTML = email; + var emailField = document.getElementById(app.prefix('-email-address')); + emailField.innerHTML = email; - var buttonIcon1 = document.getElementById(app.prefix('-button-icon-1')); - buttonIcon1.innerHTML = options.buttonIcon1; + var buttonIcon1 = document.getElementById(app.prefix('-button-icon-1')); + buttonIcon1.innerHTML = options.buttonIcon1; - var buttonIcon2 = document.getElementById(app.prefix('-button-icon-2')); - buttonIcon2.innerHTML = options.buttonIcon2; + var buttonIcon2 = document.getElementById(app.prefix('-button-icon-2')); + buttonIcon2.innerHTML = options.buttonIcon2; - var buttonIcon3 = document.getElementById(app.prefix('-button-icon-3')); - buttonIcon3.innerHTML = options.buttonIcon3; + var buttonIcon3 = document.getElementById(app.prefix('-button-icon-3')); + buttonIcon3.innerHTML = options.buttonIcon3; - var buttonIcon4 = document.getElementById(app.prefix('-button-icon-4')); - buttonIcon4.innerHTML = options.buttonIcon4; + var buttonIcon4 = document.getElementById(app.prefix('-button-icon-4')); + buttonIcon4.innerHTML = options.buttonIcon4; - var buttonIconCopy = document.getElementById(app.prefix('-button-icon-copy')); - buttonIconCopy.innerHTML = options.buttonIconCopy; + var buttonIconCopy = document.getElementById(app.prefix('-button-icon-copy')); + buttonIconCopy.innerHTML = options.buttonIconCopy; - app.toggleHideCopyUi(email); - }; + app.toggleHideCopyUi(email); + }; - /** + /** * When the modal is displayed, the "no-scroll" class sets the body's position to fixed. This has the * side effect of the page getting scrolled to the top. To counter that, we need to save the scroll * position when the modal is displayed, so it can be restored later on when the modal is closed. */ - app.savePageScrollPosition = function() { - scrollPosition = window.pageYOffset; - body.style.top = -scrollPosition + 'px'; - }; + app.savePageScrollPosition = function() { + scrollPosition = window.pageYOffset; + body.style.top = -scrollPosition + 'px'; + }; - /** + /** * When the modal is closed, we need to reset the page scroll position. Needed due to * the position:fixed being set by the "no-scroll" class on the body element when * the modal is open. Refer to savePageScrollPosition() method for details. */ - app.restorePageScrollPosition = function() { - window.scrollTo(0, scrollPosition); - body.style.top = 0; - }; + app.restorePageScrollPosition = function() { + window.scrollTo(0, scrollPosition); + body.style.top = 0; + }; - /** + /** * Save the page's current scroll behavior AND set it to auto, in case the current * scroll behavior is set to smooth. This prevents smooth scrolling from showing * when scrollPosition is restored via restorePageScrollPosition() method. */ - app.saveScrollBehavior = function() { - scrollBehavior = html.style.scrollBehavior; - html.style.scrollBehavior = 'auto'; - }; + app.saveScrollBehavior = function() { + scrollBehavior = html.style.scrollBehavior; + html.style.scrollBehavior = 'auto'; + }; - /** + /** * Restore the original page scroll behavior saved by saveScrollBehavior(). */ - app.restoreScrollBehavior = function() { - html.style.scrollBehavior = scrollBehavior; - }; + app.restoreScrollBehavior = function() { + html.style.scrollBehavior = scrollBehavior; + }; - /** + /** * Save the last doc element to have focus before displaying modal, * so that we can reset focus to it when the modal is closed. */ - app.saveLastDocElementFocused = function() { - lastDocElementFocused = document.activeElement; - }; + app.saveLastDocElementFocused = function() { + lastDocElementFocused = document.activeElement; + }; - /** + /** * Open modal. * * @param {Object} event The object created by the event. */ - app.openModal = function(event) { - if (options.disableOnMobile && app.isMobileDevice()) { - return; - } + app.openModal = function(event) { + if (options.disableOnMobile && app.isMobileDevice()) { + return; + } - event.preventDefault(); + event.preventDefault(); - app.saveLastDocElementFocused(); - app.savePageScrollPosition(); - app.saveScrollBehavior(); + app.saveLastDocElementFocused(); + app.savePageScrollPosition(); + app.saveScrollBehavior(); - app.displayModal(event); + app.displayModal(event); - app.hideModalFromScreenReader(false); - app.enablePageScrolling(false); - app.modalFocus(); - app.triggerEvent(modal, 'open'); - }; + app.hideModalFromScreenReader(false); + app.enablePageScrolling(false); + app.modalFocus(); + app.triggerEvent(modal, 'open'); + }; - /** + /** * Display modal and carry out other tasks needed when modal is open. * * @param {Object} event The object created by the event. */ - app.displayModal = function(event) { - var link = app.getParentElement(event.target, 'a'); - modal = app.getModal(link); - modal.style.display = 'block'; - }; + app.displayModal = function(event) { + var link = app.getParentElement(event.target, 'a'); + modal = app.getModal(link); + modal.style.display = 'block'; + }; - /** + /** * Set focus on the first button in the modal. */ - app.modalFocus = function() { - modal.focusableChildren = Array.from(modal.querySelectorAll(focusable)); - modal.focusableChildren[1].focus(); - }; + app.modalFocus = function() { + modal.focusableChildren = Array.from(modal.querySelectorAll(focusable)); + modal.focusableChildren[1].focus(); + }; - /** + /** * Close modal. * * @param {Object} event The object created by the event. */ - app.closeModal = function(event) { - event.preventDefault(); + app.closeModal = function(event) { + event.preventDefault(); - app.hideModal(); + app.hideModal(); - app.enablePageScrolling(true); - app.restorePageScrollPosition(); - app.restoreScrollBehavior(); - app.docRefocus(); - app.triggerEvent(modal, 'close'); - }; + app.enablePageScrolling(true); + app.restorePageScrollPosition(); + app.restoreScrollBehavior(); + app.docRefocus(); + app.triggerEvent(modal, 'close'); + }; - /** + /** * Hide modal. */ - app.hideModal = function() { - app.hideModalFromScreenReader(true); + app.hideModal = function() { + app.hideModalFromScreenReader(true); - if (app.isDefined(modal)) { - modal.style.display = 'none'; - } - }; + if (app.isDefined(modal)) { + modal.style.display = 'none'; + } + }; - /** + /** * Set aria attributes to hide modal from screen readers. * * @param {Boolean} hidden True to hide modal from screen reader. False otherwise. */ - app.hideModalFromScreenReader = function(hidden) { - if (app.isDefined(modal)) { - modal.setAttribute('aria-hidden', hidden); - } - }; + app.hideModalFromScreenReader = function(hidden) { + if (app.isDefined(modal)) { + modal.setAttribute('aria-hidden', hidden); + } + }; - /** + /** * Toggle a css class to enable/disable page scrolling. * * @param {Boolean} enabled True to enable page scrolling. False to disable it. */ - app.enablePageScrolling = function(enabled) { - if (enabled) { - body.classList.remove(app.prefix('-no-scroll')); - html.classList.remove(app.prefix('-no-scroll')); - } else { - body.classList.add(app.prefix('-no-scroll')); - html.classList.add(app.prefix('-no-scroll')); - } - }; + app.enablePageScrolling = function(enabled) { + if (enabled) { + body.classList.remove(app.prefix('-no-scroll')); + html.classList.remove(app.prefix('-no-scroll')); + } else { + body.classList.add(app.prefix('-no-scroll')); + html.classList.add(app.prefix('-no-scroll')); + } + }; - /** + /** * Set focus back on the last element focused on the page. */ - app.docRefocus = function() { - lastDocElementFocused.focus(); - }; + app.docRefocus = function() { + lastDocElementFocused.focus(); + }; - /** + /** * Open the given client link element. * * @param {Element} element The client link that was clicked. * @param {Object} event The object created by the event. */ - app.openClient = function(element, event) { - var target = '_blank'; + app.openClient = function(element, event) { + var target = '_blank'; - if (app.isDefaultEmailAppButton(element)) { - target = '_self'; - } + if (app.isDefaultEmailAppButton(element)) { + target = '_self'; + } - window.open(element.href, target); + window.open(element.href, target); - app.triggerEvent(element, 'compose'); + app.triggerEvent(element, 'compose'); - if (options.autoClose) { - app.closeModal(event); - } - }; + if (options.autoClose) { + app.closeModal(event); + } + }; - /** + /** * Determine if the given element is the Default Email App button. * * @param {Element} element The element to be checked. * @return {Boolean} True if the given element's id corresponds to button 4. */ - app.isDefaultEmailAppButton = function(element) { - return element.id == app.prefix('-button-4'); - }; + app.isDefaultEmailAppButton = function(element) { + return element.id == app.prefix('-button-4'); + }; - /** + /** * When an anchor tag () contains other elements, the element returned can vary * depending on where you click. We need to search up the DOM tree until we find * the parent anchor tag, which is the element that was intended to be clicked. @@ -564,562 +512,563 @@ var mailymailyApp = mailymailyApp || {}; * @param {Element} element The element that was clicked. * @return {Element} The parent anchor tag of the element that was clicked. */ - app.getParentElement = function(element, parentTag) { - while (element !== null) { - if (element.tagName.toUpperCase() == parentTag.toUpperCase()) { - return element; - } + app.getParentElement = function(element, parentTag) { + while (element !== null) { + if (element.tagName.toUpperCase() == parentTag.toUpperCase()) { + return element; + } - element = element.parentNode; - } + element = element.parentNode; + } - return null; - }; + return null; + }; - /** + /** * Fire up an event for the given element. * * @param {Element} element Trigger event for this element. * @param {String} eventName The name of the event to be triggered. */ - app.triggerEvent = function(element, eventName) { - var event = new Event(eventName); + app.triggerEvent = function(element, eventName) { + var event = new Event(eventName); - element.dispatchEvent(event); - }; + element.dispatchEvent(event); + }; - /** + /** * Check if device is a mobile phone or tablet. */ - app.isMobileDevice = function() { - var check = false; + app.isMobileDevice = function() { + var check = false; - (function(a) { - if ( - /(android|bb\d+|meego).+mobile|avantgo|bada\/|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od)|iris|kindle|lge |maemo|midp|mmp|mobile.+firefox|netfront|opera m(ob|in)i|palm( os)?|phone|p(ixi|re)\/|plucker|pocket|psp|series(4|6)0|symbian|treo|up\.(browser|link)|vodafone|wap|windows ce|xda|xiino|android|ipad|playbook|silk/i.test( - a - ) || - /1207|6310|6590|3gso|4thp|50[1-6]i|770s|802s|a wa|abac|ac(er|oo|s\-)|ai(ko|rn)|al(av|ca|co)|amoi|an(ex|ny|yw)|aptu|ar(ch|go)|as(te|us)|attw|au(di|\-m|r |s )|avan|be(ck|ll|nq)|bi(lb|rd)|bl(ac|az)|br(e|v)w|bumb|bw\-(n|u)|c55\/|capi|ccwa|cdm\-|cell|chtm|cldc|cmd\-|co(mp|nd)|craw|da(it|ll|ng)|dbte|dc\-s|devi|dica|dmob|do(c|p)o|ds(12|\-d)|el(49|ai)|em(l2|ul)|er(ic|k0)|esl8|ez([4-7]0|os|wa|ze)|fetc|fly(\-|_)|g1 u|g560|gene|gf\-5|g\-mo|go(\.w|od)|gr(ad|un)|haie|hcit|hd\-(m|p|t)|hei\-|hi(pt|ta)|hp( i|ip)|hs\-c|ht(c(\-| |_|a|g|p|s|t)|tp)|hu(aw|tc)|i\-(20|go|ma)|i230|iac( |\-|\/)|ibro|idea|ig01|ikom|im1k|inno|ipaq|iris|ja(t|v)a|jbro|jemu|jigs|kddi|keji|kgt( |\/)|klon|kpt |kwc\-|kyo(c|k)|le(no|xi)|lg( g|\/(k|l|u)|50|54|\-[a-w])|libw|lynx|m1\-w|m3ga|m50\/|ma(te|ui|xo)|mc(01|21|ca)|m\-cr|me(rc|ri)|mi(o8|oa|ts)|mmef|mo(01|02|bi|de|do|t(\-| |o|v)|zz)|mt(50|p1|v )|mwbp|mywa|n10[0-2]|n20[2-3]|n30(0|2)|n50(0|2|5)|n7(0(0|1)|10)|ne((c|m)\-|on|tf|wf|wg|wt)|nok(6|i)|nzph|o2im|op(ti|wv)|oran|owg1|p800|pan(a|d|t)|pdxg|pg(13|\-([1-8]|c))|phil|pire|pl(ay|uc)|pn\-2|po(ck|rt|se)|prox|psio|pt\-g|qa\-a|qc(07|12|21|32|60|\-[2-7]|i\-)|qtek|r380|r600|raks|rim9|ro(ve|zo)|s55\/|sa(ge|ma|mm|ms|ny|va)|sc(01|h\-|oo|p\-)|sdk\/|se(c(\-|0|1)|47|mc|nd|ri)|sgh\-|shar|sie(\-|m)|sk\-0|sl(45|id)|sm(al|ar|b3|it|t5)|so(ft|ny)|sp(01|h\-|v\-|v )|sy(01|mb)|t2(18|50)|t6(00|10|18)|ta(gt|lk)|tcl\-|tdg\-|tel(i|m)|tim\-|t\-mo|to(pl|sh)|ts(70|m\-|m3|m5)|tx\-9|up(\.b|g1|si)|utst|v400|v750|veri|vi(rg|te)|vk(40|5[0-3]|\-v)|vm40|voda|vulc|vx(52|53|60|61|70|80|81|83|85|98)|w3c(\-| )|webc|whit|wi(g |nc|nw)|wmlb|wonu|x700|yas\-|your|zeto|zte\-/i.test( - a.substr(0, 4) - ) - ) { - check = true; - } - })(navigator.userAgent || navigator.vendor || window.opera); - return check; - }; + (function(a) { + if ( + /(android|bb\d+|meego).+mobile|avantgo|bada\/|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od)|iris|kindle|lge |maemo|midp|mmp|mobile.+firefox|netfront|opera m(ob|in)i|palm( os)?|phone|p(ixi|re)\/|plucker|pocket|psp|series(4|6)0|symbian|treo|up\.(browser|link)|vodafone|wap|windows ce|xda|xiino|android|ipad|playbook|silk/i.test( + a + ) || + /1207|6310|6590|3gso|4thp|50[1-6]i|770s|802s|a wa|abac|ac(er|oo|s\-)|ai(ko|rn)|al(av|ca|co)|amoi|an(ex|ny|yw)|aptu|ar(ch|go)|as(te|us)|attw|au(di|\-m|r |s )|avan|be(ck|ll|nq)|bi(lb|rd)|bl(ac|az)|br(e|v)w|bumb|bw\-(n|u)|c55\/|capi|ccwa|cdm\-|cell|chtm|cldc|cmd\-|co(mp|nd)|craw|da(it|ll|ng)|dbte|dc\-s|devi|dica|dmob|do(c|p)o|ds(12|\-d)|el(49|ai)|em(l2|ul)|er(ic|k0)|esl8|ez([4-7]0|os|wa|ze)|fetc|fly(\-|_)|g1 u|g560|gene|gf\-5|g\-mo|go(\.w|od)|gr(ad|un)|haie|hcit|hd\-(m|p|t)|hei\-|hi(pt|ta)|hp( i|ip)|hs\-c|ht(c(\-| |_|a|g|p|s|t)|tp)|hu(aw|tc)|i\-(20|go|ma)|i230|iac( |\-|\/)|ibro|idea|ig01|ikom|im1k|inno|ipaq|iris|ja(t|v)a|jbro|jemu|jigs|kddi|keji|kgt( |\/)|klon|kpt |kwc\-|kyo(c|k)|le(no|xi)|lg( g|\/(k|l|u)|50|54|\-[a-w])|libw|lynx|m1\-w|m3ga|m50\/|ma(te|ui|xo)|mc(01|21|ca)|m\-cr|me(rc|ri)|mi(o8|oa|ts)|mmef|mo(01|02|bi|de|do|t(\-| |o|v)|zz)|mt(50|p1|v )|mwbp|mywa|n10[0-2]|n20[2-3]|n30(0|2)|n50(0|2|5)|n7(0(0|1)|10)|ne((c|m)\-|on|tf|wf|wg|wt)|nok(6|i)|nzph|o2im|op(ti|wv)|oran|owg1|p800|pan(a|d|t)|pdxg|pg(13|\-([1-8]|c))|phil|pire|pl(ay|uc)|pn\-2|po(ck|rt|se)|prox|psio|pt\-g|qa\-a|qc(07|12|21|32|60|\-[2-7]|i\-)|qtek|r380|r600|raks|rim9|ro(ve|zo)|s55\/|sa(ge|ma|mm|ms|ny|va)|sc(01|h\-|oo|p\-)|sdk\/|se(c(\-|0|1)|47|mc|nd|ri)|sgh\-|shar|sie(\-|m)|sk\-0|sl(45|id)|sm(al|ar|b3|it|t5)|so(ft|ny)|sp(01|h\-|v\-|v )|sy(01|mb)|t2(18|50)|t6(00|10|18)|ta(gt|lk)|tcl\-|tdg\-|tel(i|m)|tim\-|t\-mo|to(pl|sh)|ts(70|m\-|m3|m5)|tx\-9|up(\.b|g1|si)|utst|v400|v750|veri|vi(rg|te)|vk(40|5[0-3]|\-v)|vm40|voda|vulc|vx(52|53|60|61|70|80|81|83|85|98)|w3c(\-| )|webc|whit|wi(g |nc|nw)|wmlb|wonu|x700|yas\-|your|zeto|zte\-/i.test( + a.substr(0, 4) + ) + ) { + check = true; + } + })(navigator.userAgent || navigator.vendor || window.opera); + return check; + }; - /** + /** * Listen for events. */ - app.listenForEvents = function() { - app.listenForClickOnLink(); - app.listenForClickOnClient(); - app.listenForClickOnCopy(); - app.listenForClickOnClose(); - app.listenForClickOnWindow(); - app.listenForKeys(); - }; + app.listenForEvents = function() { + app.listenForClickOnLink(); + app.listenForClickOnClient(); + app.listenForClickOnCopy(); + app.listenForClickOnClose(); + app.listenForClickOnWindow(); + app.listenForKeys(); + }; - /** + /** * Listen for click event on mailto links. */ - app.listenForClickOnLink = function() { - var links = document.getElementsByClassName(app.prefix()); + app.listenForClickOnLink = function() { + var links = document.getElementsByClassName(app.prefix()); - for (var i = 0; i < links.length; i++) { - links[i].addEventListener( - 'click', - function(event) { - app.openModal(event); - }, - false - ); - } - }; + for (var i = 0; i < links.length; i++) { + links[i].addEventListener( + 'click', + function(event) { + app.openModal(event); + }, + false + ); + } + }; - /** + /** * Listen for click event on client links. */ - app.listenForClickOnClient = function() { - var clients = document.getElementsByClassName(app.prefix('-button')); + app.listenForClickOnClient = function() { + var clients = document.getElementsByClassName(app.prefix('-button')); - for (var i = 0; i < clients.length; i++) { - clients[i].addEventListener( - 'click', - function(event) { - event.preventDefault(); - event.stopPropagation(); + for (var i = 0; i < clients.length; i++) { + clients[i].addEventListener( + 'click', + function(event) { + event.preventDefault(); + event.stopPropagation(); - var client = app.getParentElement(event.target, 'a'); + var client = app.getParentElement(event.target, 'a'); - app.openClient(client, event); - }, - false - ); - } - }; + app.openClient(client, event); + }, + false + ); + } + }; - /** + /** * Listen for click event on Copy button. */ - app.listenForClickOnCopy = function() { - var copyButton = document.getElementById(app.prefix('-button-copy')); + app.listenForClickOnCopy = function() { + var copyButton = document.getElementById(app.prefix('-button-copy')); - copyButton.addEventListener( - 'click', - function(event) { - app.copy(event); - }, - false - ); - }; + copyButton.addEventListener( + 'click', + function(event) { + app.copy(event); + }, + false + ); + }; - /** + /** * Listen for click event on Close button. */ - app.listenForClickOnClose = function() { - var closeButton = document.getElementById(app.prefix('-modal-close')); + app.listenForClickOnClose = function() { + var closeButton = document.getElementById(app.prefix('-modal-close')); - closeButton.addEventListener( - 'click', - function(event) { - app.closeModal(event); - }, - false - ); - }; + closeButton.addEventListener( + 'click', + function(event) { + app.closeModal(event); + }, + false + ); + }; - /** + /** * Listen for click event on window (to close modal). */ - app.listenForClickOnWindow = function() { - window.addEventListener( - 'click', - function(event) { - var element = event.target; + app.listenForClickOnWindow = function() { + window.addEventListener( + 'click', + function(event) { + var element = event.target; - if (element !== null && element.classList.contains(app.prefix('-modal'))) { - app.closeModal(event); - } - }, - false - ); - }; + if (element !== null && element.classList.contains(app.prefix('-modal'))) { + app.closeModal(event); + } + }, + false + ); + }; - /** + /** * Listen for keydown events to escape modal or tab within it. */ - app.listenForKeys = function() { - document.addEventListener( - 'keydown', - function(event) { - app.escapeModal(event); - app.trapTabWithinModal(event); - }, - false - ); - }; + app.listenForKeys = function() { + document.addEventListener( + 'keydown', + function(event) { + app.escapeModal(event); + app.trapTabWithinModal(event); + }, + false + ); + }; - /** + /** * Close modal when Esc key is pressed. * * @param {KeyboardEvent} event The event generated by pressing a key. */ - app.escapeModal = function(event) { - if (event.keyCode === 27) { - app.closeModal(event); - } - }; + app.escapeModal = function(event) { + if (event.keyCode === 27) { + app.closeModal(event); + } + }; - /** + /** * Should not be able to tab outside the modal. Pressing the tab * key moves focus to the next focusable element within modal. * * @param {KeyboardEvent} event The event generated by pressing a key. */ - app.trapTabWithinModal = function(event) { - if (event.keyCode === 9 && modal !== null) { - var currentFocus = document.activeElement; - var totalFocusable = modal.focusableChildren.length; - var focusedIndex = modal.focusableChildren.indexOf(currentFocus); + app.trapTabWithinModal = function(event) { + if (event.keyCode === 9 && modal !== null) { + var currentFocus = document.activeElement; + var totalFocusable = modal.focusableChildren.length; + var focusedIndex = modal.focusableChildren.indexOf(currentFocus); - if (event.shiftKey) { - if (focusedIndex === 0) { - event.preventDefault(); - modal.focusableChildren[totalFocusable - 1].focus(); - } - } else { - if (focusedIndex == totalFocusable - 1) { - event.preventDefault(); - modal.focusableChildren[0].focus(); - } - } - } - }; + if (event.shiftKey) { + if (focusedIndex === 0) { + event.preventDefault(); + modal.focusableChildren[totalFocusable - 1].focus(); + } + } else { + if (focusedIndex == totalFocusable - 1) { + event.preventDefault(); + modal.focusableChildren[0].focus(); + } + } + } + }; - /** + /** * Get all "mailymaily" links on the page. * * @return {HTMLCollection} All links with the class "mailymaily" (default). */ - app.getLinks = function() { - return document.getElementsByClassName(app.prefix()); - }; + app.getLinks = function() { + return document.getElementsByClassName(app.prefix()); + }; - /** + /** * Split the URL scheme of given link in two strings: the email address, and the * key-value query string. Also remove 'mailto:' to get nice clean values. * * @param {Element} link The link element clicked. * @return {Array} The two parts of the link scheme separated at '?'. */ - app.splitLink = function(link) { - var scheme = link.href.replace('mailto:', '').trim(); - var parts = scheme.split('?', 1); + app.splitLink = function(link) { + var scheme = link.href.replace('mailto:', '').trim(); + var parts = scheme.split('?', 1); - if (parts !== null && parts.length > 0) { - parts[1] = scheme.replace(parts[0] + '?', '').trim(); - } + if (parts !== null && parts.length > 0) { + parts[1] = scheme.replace(parts[0] + '?', '').trim(); + } - return parts; - }; + return parts; + }; - /** + /** * Extract the value of the given field from the link. * * @param {Element} link The link element clicked. * @param {String} field The name of the field we want to get. * @return {String} The value corresponding to the given field. */ - app.getLinkField = function(link, field) { - var parts = app.splitLink(link); - var query = ''; - var terms = []; - var keyValues = []; - var value = ''; + app.getLinkField = function(link, field) { + var parts = app.splitLink(link); + var query = ''; + var terms = []; + var keyValues = []; + var value = ''; - if (parts !== null && parts.length > 0) { - query = parts[1]; - } + if (parts !== null && parts.length > 0) { + query = parts[1]; + } - if (query !== null && query.length > 0) { - // Encode any instance of ' & ' inside field values to prevent spliting at the wrong place. - query = query.replace('%20&%20', '%20%26%20'); + if (query !== null && query.length > 0) { + // Encode any instance of ' & ' inside field values to prevent spliting at the wrong place. + query = query.replace('%20&%20', '%20%26%20'); - terms = query.split('&'); - } + terms = query.split('&'); + } - for (var i = 0; i < terms.length; i++) { - // Encode any instance of ' = ' inside field values to prevent spliting at the wrong place. - terms[i] = terms[i].replace('%20=%20', '%20%3D%20'); + for (var i = 0; i < terms.length; i++) { + // Encode any instance of ' = ' inside field values to prevent spliting at the wrong place. + terms[i] = terms[i].replace('%20=%20', '%20%3D%20'); - keyValues = terms[i].split('='); + keyValues = terms[i].split('='); - for (var n = 0; n < keyValues.length; n++) { - if (keyValues[0] == field) { - return keyValues[1]; - } - } - } + for (var n = 0; n < keyValues.length; n++) { + if (keyValues[0] == field) { + return keyValues[1]; + } + } + } - return value; - }; + return value; + }; - /** + /** * Extract email address from mailto string. * * @param {Element} link The link element clicked. * @return {String} The email address. */ - app.getEmail = function(link) { - var parts = app.splitLink(link); - var email = ''; + app.getEmail = function(link) { + var parts = app.splitLink(link); + var email = ''; - if (parts !== null && parts.length > 0) { - email = parts[0]; - } + if (parts !== null && parts.length > 0) { + email = parts[0]; + } - return decodeURIComponent(email); - }; + return decodeURIComponent(email); + }; - /** + /** * Build and return the class name used to hide the Copy UI. * * @return {String} The CSS class name needed to hide the Copy UI. */ - app.getClassHideCopyUi = function() { - return app.prefix('-is-hidden'); - }; + app.getClassHideCopyUi = function() { + return app.prefix('-is-hidden'); + }; - /** + /** * Show or hide the Copy UI based on email address presence. * * @param {String} email The email address to be checked. */ - app.toggleHideCopyUi = function(email) { - var copyUi = document.getElementById(app.prefix('-copy')); + app.toggleHideCopyUi = function(email) { + var copyUi = document.getElementById(app.prefix('-copy')); - if (email.length == 0) { - copyUi.classList.add(app.getClassHideCopyUi()); - } else { - copyUi.classList.remove(app.getClassHideCopyUi()); - } - }; + if (email.length == 0) { + copyUi.classList.add(app.getClassHideCopyUi()); + } else { + copyUi.classList.remove(app.getClassHideCopyUi()); + } + }; - /** + /** * Set copy button text to indicate the email address has been copied. */ - app.toggleCopyButton = function() { - button = document.getElementById(app.prefix('-button-copy')); - buttonText = document.getElementById(app.prefix('-button-text-copy')); - buttonText.innerHTML = options.buttonTextCopyAction; - button.classList.add(app.prefix('-button-copy-clicked')); + app.toggleCopyButton = function() { + button = document.getElementById(app.prefix('-button-copy')); + buttonText = document.getElementById(app.prefix('-button-text-copy')); + buttonText.innerHTML = options.buttonTextCopyAction; + button.classList.add(app.prefix('-button-copy-clicked')); - setTimeout(function() { - buttonText.innerHTML = options.buttonTextCopy; - button.classList.remove(app.prefix('-button-copy-clicked')); - }, 600); - }; + setTimeout(function() { + buttonText.innerHTML = options.buttonTextCopy; + button.classList.remove(app.prefix('-button-copy-clicked')); + }, 600); + }; - /** + /** * Copy email address to the clipboard. * * @param {String} event The event generated by clicking on Copy button. */ - app.copy = function(event) { - event.preventDefault(); + app.copy = function(event) { + event.preventDefault(); - var targetId = app.getParentElement(event.target, 'button').getAttribute('data-copytargetid'); - var email = document.getElementById(targetId); - var range = document.createRange(); + var targetId = app.getParentElement(event.target, 'button').getAttribute('data-copytargetid'); + var email = document.getElementById(targetId); + var range = document.createRange(); - range.selectNodeContents(email); + range.selectNodeContents(email); - var selection = window.getSelection(); - selection.removeAllRanges(); - selection.addRange(range); + var selection = window.getSelection(); + selection.removeAllRanges(); + selection.addRange(range); - document.execCommand('copy'); - app.triggerEvent(email, 'copy'); + document.execCommand('copy'); + app.triggerEvent(email, 'copy'); - app.toggleCopyButton(); - }; + app.toggleCopyButton(); + }; - /** + /** * Check if device is running iOS. * * @return {Boolean} True if device runs iOS. */ - app.isiOSDevice = function() { - return navigator.userAgent.match(/ipad|iphone/i); - }; + app.isiOSDevice = function() { + return navigator.userAgent.match(/ipad|iphone/i); + }; - /** + /** * Get user options provided as an object parameter in the run * method, or as a JSON string provided in a data attribute * of the script tag. Save all in the options object. * * @param {Object} optionsObj An object containing user options. */ - app.setOptions = function(optionsObj) { - if (optionsObj) { - var userOptions = JSON.stringify(optionsObj); - } else { - var userOptions = app.getOptionsFromScriptTag(); - } + app.setOptions = function(optionsObj) { + if (optionsObj) { + var userOptions = JSON.stringify(optionsObj); + } else { + var userOptions = app.getOptionsFromScriptTag(); + } - if (userOptions && userOptions.trim().length > 0) { - userOptions = JSON.parse(userOptions); + if (userOptions && userOptions.trim().length > 0) { + userOptions = JSON.parse(userOptions); - for (var name in options) { - if (userOptions.hasOwnProperty(name)) { - options[name] = app.sanitizeUserOption(name, userOptions[name]); - } - } - } - }; + for (var name in options) { + if (userOptions.hasOwnProperty(name)) { + options[name] = app.sanitizeUserOption(name, userOptions[name]); + } + } + } + }; - /** + /** * Clean up given user options. * * @param {String} name The name of the user option to be sanitized. * @param {mixed} value The value of the user option. * @return {mixed} The sanitized value when applicable, or the original value. */ - app.sanitizeUserOption = function(name, value) { - if (app.stringContains(name, 'icon')) { - return app.validateSvg(name, value); - } + app.sanitizeUserOption = function(name, value) { + if (app.stringContains(name, 'icon')) { + return app.validateSvg(name, value); + } - if (app.isString(value)) { - return app.stripHtml(value); - } + if (app.isString(value)) { + return app.stripHtml(value); + } - return value; - }; + return value; + }; - /** + /** * Check svg file for possible problems or tampering. * * @param {String} name The name of an 'icon' user option (must exist in options array). * @param {String} url The url to an svg file. */ - app.validateSvg = function(name, url) { - app.getSvg(name, url) - .then(function(promise) { - if (!app.stringIsSvg(promise.responseText)) { - throw new Error(name + ': ' + url + ' is not an SVG file.'); - } + app.validateSvg = function(name, url) { + app + .getSvg(name, url) + .then(function(promise) { + if (!app.stringIsSvg(promise.responseText)) { + throw new Error(name + ': ' + url + ' is not an SVG file.'); + } - if (app.stringHasScript(promise.responseText)) { - throw new Error(name + ': ' + url + ' is an invalid SVG file.'); - } else { - options[name] = promise.responseText; - } - }) - .catch(function(error) { - if (name == 'buttonIconCopy') { - options[name] = clipboardSvg; - } else { - options[name] = worldSvg; - } - console.log(error); - }); - }; + if (app.stringHasScript(promise.responseText)) { + throw new Error(name + ': ' + url + ' is an invalid SVG file.'); + } else { + options[name] = promise.responseText; + } + }) + .catch(function(error) { + if (name == 'buttonIconCopy') { + options[name] = clipboardSvg; + } else { + options[name] = worldSvg; + } + console.log(error); + }); + }; - /** + /** * Load an svg file from the given url. * * @param {String} name The name of an 'icon' user option (must exist in options array). * @param {String} url The url to an svg file. * @return {Promise} The resolved or rejected promise after ajax call to load svg file. */ - app.loadSvg = function(name, url) { - return new Promise((resolve, reject) => { - var ajax = new XMLHttpRequest(); + app.loadSvg = function(name, url) { + return new Promise((resolve, reject) => { + var ajax = new XMLHttpRequest(); - ajax.open('GET', url, true); + ajax.open('GET', url, true); - ajax.onload = function(event) { - if (ajax.status == 200) { - resolve(ajax); - } else { - reject(ajax); - } - }; + ajax.onload = function(event) { + if (ajax.status == 200) { + resolve(ajax); + } else { + reject(ajax); + } + }; - ajax.send(); - }); - }; + ajax.send(); + }); + }; - /** + /** * Async method to load svg file from given url. * * @param {String} name The name of an 'icon' user option (must exist in options array). * @param {String} url The url to an svg file. * @return {Promise} The Promise with the result returned by loadSvg(). */ - app.getSvg = async function(name, url) { - return await app.loadSvg(name, url); - }; + app.getSvg = async function(name, url) { + return await app.loadSvg(name, url); + }; - /** + /** * Check if given value is a string. * * @param {mixed} value The value to be checked. * @return {Boolean} True if value is a string. False otherwise. */ - app.isString = function(value) { - return typeof value === 'string'; - }; + app.isString = function(value) { + return typeof value === 'string'; + }; - /** + /** * Remove html tags from given string. * * @param {String} text The string to be stripped. * @return {String} The given string stripped off markup tags. */ - app.stripHtml = function(text) { - return text.replace(/(<([^>]+)>)/g, ''); - }; + app.stripHtml = function(text) { + return text.replace(/(<([^>]+)>)/g, ''); + }; - /** + /** * Check if a string contains another string ("needle in a haystack"). * * @param {String} haystack The string where to search. * @param {String} needle The string to search for. * @return {Boolean} True if needle is found in haystack. False otherwise. */ - app.stringContains = function(haystack, needle) { - return haystack.toLowerCase().indexOf(needle.toLowerCase()) !== -1; - }; + app.stringContains = function(haystack, needle) { + return haystack.toLowerCase().indexOf(needle.toLowerCase()) !== -1; + }; - /** + /** * Check if given string is an svg file. * * @param {String} text The string to be checked. * @return {Boolean} True if string starts with ' tag. * * @param {String} text The string to be checked. * @return {Boolean} True if given string contains