diff --git a/README_tempate.md b/README_tempate.md index afe532f..ec59cba 100644 --- a/README_tempate.md +++ b/README_tempate.md @@ -1,3 +1,7 @@ + # Introduction Goodforms-js is a Javascript library that enables easy, browser-based validation of email addresses, by looking at the diff --git a/auto.js b/auto.js index 2832a40..0dbaaa5 100644 --- a/auto.js +++ b/auto.js @@ -6,15 +6,15 @@ import { duplicate } from "./utils.js" export default function (options) { let activated_forms=[] for(let form = 0 ; form < document.forms.length ; form++ ) { //olde-skoole DOM0 FTW! - log.debug("Checking form: "+form+" for verifiable email address fields...") + log.verbose("Checking form: "+form+" for verifiable email address fields...") for(let i = 0; i < document.forms[form].elements.length ; i ++ ) { - log.debug("Checking field #"+i+" to see if it's an email address field") + log.verbose("Checking field #"+i+" to see if it's an email address field") let this_field = document.forms[form].elements[i] - log.debug("It's type is: "+this_field.type+" its name is: "+this_field.name+" and its id is: "+this_field.id) + log.verbose("It's type is: "+this_field.type+" its name is: "+this_field.name+" and its id is: "+this_field.id) //log.debugdir(this_field) if(this_field.type == "email" || this_field.name == "email" || this_field.id == "email") { let options_copy = duplicate(options) - log.debug("Found candidate field. Name: "+this_field.name+" Type: "+this_field.type+" ID: "+this_field.id) + log.debug("Found candidate email field. Name: "+this_field.name+" Type: "+this_field.type+" ID: "+this_field.id) options_copy.form = document.forms[form] options_copy.email_field = this_field activated_forms.push(new Form(options_copy)) diff --git a/dist/verify.js b/dist/verify.js index 621f200..d655503 100644 --- a/dist/verify.js +++ b/dist/verify.js @@ -1,2 +1,2 @@ (function(global,factory){typeof exports==="object"&&typeof module!=="undefined"?module.exports=factory():typeof define==="function"&&define.amd?define(factory):(global=global||self,global.Goodforms=factory())})(this,function(){"use strict";var HOST="https://api.goodforms.com";var Log=function Log(debug_enabled){if(debug_enabled===void 0)debug_enabled=false;this.debug_enabled=debug_enabled};Log.prototype.error=function error(msg){if(!this.log_at_level("error",msg)){window.alert("Error: "+msg)}};Log.prototype.debug=function debug(msg){if(this.debug_enabled){this.log_at_level("debug",msg)}};Log.prototype.debugdir=function debugdir(msg){if(this.debug_enabled){if(typeof console!=="undefined"&&console["dir"]){this.log_at_level("dir",msg)}else{this.log_at_level("debug",msg)}}};Log.prototype.log_at_level=function log_at_level(level,msg){if(typeof console!=="undefined"&&console[level]){console[level](msg);return true}window.alert(level+": "+msg);return false};var log=new Log;function duplicate(obj){var newobj={};for(var i in obj){newobj[i]=obj[i]}return newobj}function is_array(obj){if(Object.prototype.toString.call(obj)=="[object Array]"){return true}return false}function is_function(functionToCheck){return functionToCheck&&{}.toString.call(functionToCheck)==="[object Function]"}var commonjsGlobal=typeof globalThis!=="undefined"?globalThis:typeof window!=="undefined"?window:typeof global!=="undefined"?global:typeof self!=="undefined"?self:{};function createCommonjsModule(fn,module){return module={exports:{}},fn(module,module.exports),module.exports}var jsonp=createCommonjsModule(function(module){(function(){var JSONP,computedUrl,createElement,encode,noop,objectToURI,random,randomString;createElement=function(tag){return window.document.createElement(tag)};encode=window.encodeURIComponent;random=Math.random;JSONP=function(options){var callback,callbackFunc,callbackName,done,head,params,script;if(options==null){options={}}params={data:options.data||{},error:options.error||noop,success:options.success||noop,beforeSend:options.beforeSend||noop,complete:options.complete||noop,url:options.url||""};params.computedUrl=computedUrl(params);if(params.url.length===0){throw new Error("MissingUrl")}done=false;if(params.beforeSend({},params)!==false){callbackName=options.callbackName||"callback";callbackFunc=options.callbackFunc||"jsonp_"+randomString(15);callback=params.data[callbackName]=callbackFunc;window[callback]=function(data){window[callback]=null;params.success(data,params);return params.complete(data,params)};script=createElement("script");script.src=computedUrl(params);script.async=true;script.onerror=function(evt){params.error({url:script.src,event:evt});return params.complete({url:script.src,event:evt},params)};script.onload=script.onreadystatechange=function(){var ref,ref1;if(done||(ref=this.readyState)!=="loaded"&&ref!=="complete"){return}done=true;if(script){script.onload=script.onreadystatechange=null;if((ref1=script.parentNode)!=null){ref1.removeChild(script)}return script=null}};head=window.document.getElementsByTagName("head")[0]||window.document.documentElement;head.insertBefore(script,head.firstChild)}return{abort:function(){window[callback]=function(){return window[callback]=null};done=true;if(script!=null?script.parentNode:void 0){script.onload=script.onreadystatechange=null;script.parentNode.removeChild(script);return script=null}}}};noop=function(){return void 0};computedUrl=function(params){var url;url=params.url;url+=params.url.indexOf("?")<0?"?":"&";url+=objectToURI(params.data);return url};randomString=function(length){var str;str="";while(str.lengtharr.length){len=arr.length}for(var i=0,arr2=new Array(len);i0){this.registerTriggers.apply(this,_toConsumableArray(triggers))}this.onClick=this.onClick.bind(this);this.onKeydown=this.onKeydown.bind(this)}_createClass(Modal,[{key:"registerTriggers",value:function registerTriggers(){var arguments$1=arguments;var _this=this;for(var _len=arguments.length,triggers=new Array(_len),_key=0;_key<_len;_key++){triggers[_key]=arguments$1[_key]}triggers.filter(Boolean).forEach(function(trigger){trigger.addEventListener("click",function(event){return _this.showModal(event)})})}},{key:"showModal",value:function showModal(){var _this2=this;var event=arguments.length>0&&arguments[0]!==undefined?arguments[0]:null;this.activeElement=document.activeElement;this.modal.setAttribute("aria-hidden","false");this.modal.classList.add(this.config.openClass);this.scrollBehaviour("disable");this.addEventListeners();if(this.config.awaitOpenAnimation){var handler=function handler(){_this2.modal.removeEventListener("animationend",handler,false);_this2.setFocusToFirstNode()};this.modal.addEventListener("animationend",handler,false)}else{this.setFocusToFirstNode()}this.config.onShow(this.modal,this.activeElement,event)}},{key:"closeModal",value:function closeModal(){var event=arguments.length>0&&arguments[0]!==undefined?arguments[0]:null;var modal=this.modal;this.modal.setAttribute("aria-hidden","true");this.removeEventListeners();this.scrollBehaviour("enable");if(this.activeElement&&this.activeElement.focus){this.activeElement.focus()}this.config.onClose(this.modal,this.activeElement,event);if(this.config.awaitCloseAnimation){var openClass=this.config.openClass;this.modal.addEventListener("animationend",function handler(){modal.classList.remove(openClass);modal.removeEventListener("animationend",handler,false)},false)}else{modal.classList.remove(this.config.openClass)}}},{key:"closeModalById",value:function closeModalById(targetModal){this.modal=document.getElementById(targetModal);if(this.modal){this.closeModal()}}},{key:"scrollBehaviour",value:function scrollBehaviour(toggle){if(!this.config.disableScroll){return}var body=document.querySelector("body");switch(toggle){case"enable":Object.assign(body.style,{overflow:""});break;case"disable":Object.assign(body.style,{overflow:"hidden"});break}}},{key:"addEventListeners",value:function addEventListeners(){this.modal.addEventListener("touchstart",this.onClick);this.modal.addEventListener("click",this.onClick);document.addEventListener("keydown",this.onKeydown)}},{key:"removeEventListeners",value:function removeEventListeners(){this.modal.removeEventListener("touchstart",this.onClick);this.modal.removeEventListener("click",this.onClick);document.removeEventListener("keydown",this.onKeydown)}},{key:"onClick",value:function onClick(event){if(event.target.hasAttribute(this.config.closeTrigger)){this.closeModal(event)}}},{key:"onKeydown",value:function onKeydown(event){if(event.keyCode===27){this.closeModal(event)}if(event.keyCode===9){this.retainFocus(event)}}},{key:"getFocusableNodes",value:function getFocusableNodes(){var nodes=this.modal.querySelectorAll(FOCUSABLE_ELEMENTS);return Array.apply(void 0,_toConsumableArray(nodes))}},{key:"setFocusToFirstNode",value:function setFocusToFirstNode(){var _this3=this;if(this.config.disableFocus){return}var focusableNodes=this.getFocusableNodes();if(focusableNodes.length===0){return}var nodesWhichAreNotCloseTargets=focusableNodes.filter(function(node){return!node.hasAttribute(_this3.config.closeTrigger)});if(nodesWhichAreNotCloseTargets.length>0){nodesWhichAreNotCloseTargets[0].focus()}if(nodesWhichAreNotCloseTargets.length===0){focusableNodes[0].focus()}}},{key:"retainFocus",value:function retainFocus(event){var focusableNodes=this.getFocusableNodes();if(focusableNodes.length===0){return}focusableNodes=focusableNodes.filter(function(node){return node.offsetParent!==null});if(!this.modal.contains(document.activeElement)){focusableNodes[0].focus()}else{var focusedItemIndex=focusableNodes.indexOf(document.activeElement);if(event.shiftKey&&focusedItemIndex===0){focusableNodes[focusableNodes.length-1].focus();event.preventDefault()}if(!event.shiftKey&&focusableNodes.length>0&&focusedItemIndex===focusableNodes.length-1){focusableNodes[0].focus();event.preventDefault()}}}}]);return Modal}();var activeModal=null;var generateTriggerMap=function generateTriggerMap(triggers,triggerAttr){var triggerMap=[];triggers.forEach(function(trigger){var targetModal=trigger.attributes[triggerAttr].value;if(triggerMap[targetModal]===undefined){triggerMap[targetModal]=[]}triggerMap[targetModal].push(trigger)});return triggerMap};var validateModalPresence=function validateModalPresence(id){if(!document.getElementById(id)){console.warn("MicroModal: ❗Seems like you have missed %c'".concat(id,"'"),"background-color: #f8f9fa;color: #50596c;font-weight: bold;","ID somewhere in your code. Refer example below to resolve it.");console.warn("%cExample:","background-color: #f8f9fa;color: #50596c;font-weight: bold;",''));return false}};var validateTriggerPresence=function validateTriggerPresence(triggers){if(triggers.length<=0){console.warn("MicroModal: ❗Please specify at least one %c'micromodal-trigger'","background-color: #f8f9fa;color: #50596c;font-weight: bold;","data attribute.");console.warn("%cExample:","background-color: #f8f9fa;color: #50596c;font-weight: bold;",'');return false}};var validateArgs=function validateArgs(triggers,triggerMap){validateTriggerPresence(triggers);if(!triggerMap){return true}for(var id in triggerMap){validateModalPresence(id)}return true};var init=function init(config){var options=Object.assign({},{openTrigger:"data-micromodal-trigger"},config);var triggers=_toConsumableArray(document.querySelectorAll("[".concat(options.openTrigger,"]")));var triggerMap=generateTriggerMap(triggers,options.openTrigger);if(options.debugMode===true&&validateArgs(triggers,triggerMap)===false){return}for(var key in triggerMap){var value=triggerMap[key];options.targetModal=key;options.triggers=_toConsumableArray(value);activeModal=new Modal(options)}};var show=function show(targetModal,config){var options=config||{};options.targetModal=targetModal;if(options.debugMode===true&&validateModalPresence(targetModal)===false){return}if(activeModal){activeModal.removeEventListeners()}activeModal=new Modal(options);activeModal.showModal()};var close=function close(targetModal){targetModal?activeModal.closeModalById(targetModal):activeModal.closeModal()};return{init:init,show:show,close:close}}();window.MicroModal=MicroModal;var css_248z='/**************************\\\n Basic Modal Styles\n\\**************************/\n\n/*\n.modal {\n display: none;\n}\n\n.modal.is-open {\n display: block;\n} */\n\n\n.modal {\n font-family: -apple-system,BlinkMacSystemFont,avenir next,avenir,helvetica neue,helvetica,ubuntu,roboto,noto,segoe ui,arial,sans-serif;\n }\n \n .modal__overlay {\n position: fixed;\n top: 0;\n left: 0;\n right: 0;\n bottom: 0;\n background: rgba(0,0,0,0.6);\n display: flex;\n justify-content: center;\n align-items: center;\n }\n \n .modal__container {\n background-color: #fff;\n padding: 30px;\n max-width: 500px;\n max-height: 100vh;\n border-radius: 4px;\n overflow-y: auto;\n box-sizing: border-box;\n }\n \n .modal__header {\n display: flex;\n justify-content: space-between;\n align-items: center;\n }\n \n .modal__title {\n margin-top: 0;\n margin-bottom: 0;\n font-weight: 600;\n font-size: 1.25rem;\n line-height: 1.25;\n color: #00449e;\n box-sizing: border-box;\n }\n \n .modal__close {\n background: transparent;\n border: 0;\n }\n \n .modal__header .modal__close:before { content: "\\2715"; }\n \n .modal__content {\n margin-top: 2rem;\n margin-bottom: 2rem;\n line-height: 1.5;\n color: rgba(0,0,0,.8);\n }\n \n .modal__btn {\n font-size: .875rem;\n padding-left: 1rem;\n padding-right: 1rem;\n padding-top: .5rem;\n padding-bottom: .5rem;\n background-color: #e6e6e6;\n color: rgba(0,0,0,.8);\n border-radius: .25rem;\n border-style: none;\n border-width: 0;\n cursor: pointer;\n -webkit-appearance: button;\n text-transform: none;\n overflow: visible;\n line-height: 1.15;\n margin: 0;\n will-change: transform;\n -moz-osx-font-smoothing: grayscale;\n -webkit-backface-visibility: hidden;\n backface-visibility: hidden;\n -webkit-transform: translateZ(0);\n transform: translateZ(0);\n transition: -webkit-transform .25s ease-out;\n transition: transform .25s ease-out;\n transition: transform .25s ease-out,-webkit-transform .25s ease-out;\n }\n \n .modal__btn:focus, .modal__btn:hover {\n -webkit-transform: scale(1.05);\n transform: scale(1.05);\n }\n \n .modal__btn-primary {\n background-color: #00449e;\n color: #fff;\n }\n \n \n \n /**************************\\\n Demo Animation Style\n \\**************************/\n @keyframes mmfadeIn {\n from { opacity: 0; }\n to { opacity: 1; }\n }\n \n @keyframes mmfadeOut {\n from { opacity: 1; }\n to { opacity: 0; }\n }\n \n @keyframes mmslideIn {\n from { transform: translateY(15%); }\n to { transform: translateY(0); }\n }\n \n @keyframes mmslideOut {\n from { transform: translateY(0); }\n to { transform: translateY(-10%); }\n }\n \n .micromodal-slide {\n display: none;\n }\n \n .micromodal-slide.is-open {\n display: block;\n }\n \n .micromodal-slide[aria-hidden="false"] .modal__overlay {\n animation: mmfadeIn .3s cubic-bezier(0.0, 0.0, 0.2, 1);\n }\n \n .micromodal-slide[aria-hidden="false"] .modal__container {\n animation: mmslideIn .3s cubic-bezier(0, 0, .2, 1);\n }\n \n .micromodal-slide[aria-hidden="true"] .modal__overlay {\n animation: mmfadeOut .3s cubic-bezier(0.0, 0.0, 0.2, 1);\n }\n \n .micromodal-slide[aria-hidden="true"] .modal__container {\n animation: mmslideOut .3s cubic-bezier(0, 0, .2, 1);\n }\n \n .micromodal-slide .modal__container,\n .micromodal-slide .modal__overlay {\n will-change: transform;\n }\n ';function styleInject(css,ref){if(ref===void 0){ref={}}var insertAt=ref.insertAt;if(!css||typeof document==="undefined"){return}var head=document.head||document.getElementsByTagName("head")[0];var style=document.createElement("style");style.type="text/css";if(insertAt==="top"){if(head.firstChild){head.insertBefore(style,head.firstChild)}else{head.appendChild(style)}}else{head.appendChild(style)}if(style.styleSheet){style.styleSheet.cssText=css}else{style.appendChild(document.createTextNode(css))}}var node_creator=function(name,attributes,text){var elem=document.createElement(name);for(var key in attributes){elem.setAttribute(key,attributes[key])}if(text){elem.appendChild(document.createTextNode(text))}return elem};function update_hidden_fields(form,checksum,status){insert_or_update_hidden("goodforms_checksum","goodforms_checksum",checksum,form);insert_or_update_hidden("goodforms_status","goodforms_status",status,form)}var insert_or_update_hidden=function(name,id,value,form){var element=document.getElementById(id);if(element){element.value=value;return}form.appendChild(node_creator("input",{type:"hidden",name:name,value:value,id:id}))};var modal=function modal(email_field){this.modal=null;this.css=false;this.email_field=email_field};modal.prototype.show=function show(challenge_key,message,button_callback){this.message=message;if(!this.css){styleInject(css_248z,{insertAt:"top"});this.css=true}this.get_modal(challenge_key);this.set_modal_action(button_callback);this.display_challenge_modal(challenge_key)};modal.prototype.hide=function hide(){if(this.modal){MicroModal.close("goodforms-modal")}};modal.prototype.set_modal_action=function set_modal_action(callback){this.button.onclick=callback};modal.prototype.get_challenge_address=function get_challenge_address(){return document.getElementById("goodforms_challenge_address").value};modal.prototype.get_pin_code=function get_pin_code(){return document.getElementById("goodforms_pin").value};modal.prototype.get_modal=function get_modal(challenge_key){log.debug("Getting modal - challenge key is: "+challenge_key);if(!this.modal){var modal=node_creator("div",{id:"goodforms-modal","aria-hidden":"true",class:"modal micromodal-slide"});var overlay=node_creator("div",{tabindex:"-1","data-micromodal-close":"",class:"modal__overlay"});var container=node_creator("div",{role:"dialog","aria-modal":"true","aria-labelledby":"modal-1-title",class:"modal__container"});var header=node_creator("header",{class:"modal__header"});var close_button=node_creator("button",{"aria-label":"Close modal","data-micromodal-close":"",class:"modal__close"});header.appendChild(close_button);var content=node_creator("div",{id:"modal-1-content",class:"modal__content"},this.message+". "+"To verify your email address, we need to send you an email. If you agree, re-type your email here: ");var input=node_creator("input",{type:"text",id:"goodforms_challenge_address"});content.appendChild(input);var footer=node_creator("footer",{class:"modal__footer"});var button=node_creator("button",{class:"modal__btn modal__btn-primary"},"Continue");this.button=button;footer.appendChild(button);footer.appendChild(node_creator("button",{class:"modal__btn","data-micromodal-close":"","aria-label":"Close this dialog window"},"Close"));container.appendChild(header);container.appendChild(content);container.appendChild(footer);overlay.appendChild(container);modal.appendChild(overlay);document.body.appendChild(modal);this.modal=modal}return this.modal};modal.prototype.display_challenge_modal=function display_challenge_modal(challenge_key){var this$1=this;this.get_modal(challenge_key);MicroModal.show("goodforms-modal",{debugMode:true,awaitCloseAnimation:true,onShow:function(modal){return log.debug(modal.id+" is shown")},onClose:function(modal){log.debug(modal.id+" is hidden");if(this$1.modal){document.body.removeChild(this$1.modal);delete this$1.modal}else{log.debug("Modal's onClose method is invoked and yet 'this.modal' doesn't seem to exist? Ignoring...")}}})};modal.prototype.bad_address=function bad_address(){document.getElementById("modal-1-content").innerHTML="Email doesn't match field on form! Please retry: "};modal.prototype.pin_input=function pin_input(){document.getElementById("modal-1-content").innerHTML="Input emailed PIN: "};modal.prototype.bad_pin=function bad_pin(){document.getElementById("modal-1-content").innerHTML="Invalid PIN entered. Please retry.
Input emailed PIN: "};var tooltip_html='\x3c!-- We might want to pull these styles out so that they can be overridden by end-users if they so desire --\x3e\n\n X Here is my popup\n';var tooltip=function tooltip(email_field){this.reference=email_field};tooltip.prototype.show=function show(contents){document.body.insertAdjacentHTML("beforeend",tooltip_html);this.tooltip=document.body.lastChild;this.tooltip.innerHTML=contents;this.tooltip.style.position="absolute";var rect=this.reference.getBoundingClientRect();this.tooltip.style.left=rect.x+window.scrollX+"px";this.tooltip.style.top=rect.bottom+window.scrollY+"px";this.tooltip.style.visibility="visible"};tooltip.prototype.hide=function hide(){var this$1=this;if(!this.tooltip){return}this.tooltip.style.color="177305";this.tooltip.innerHTML="valid email";this.tooltip.style.transition="visibility 0s 2s, opacity 2s linear";this.tooltip.style.opacity=0;this.tooltip.style.visibility="hidden";window.setTimeout(function(){this$1.remove()},2100)};tooltip.prototype.remove=function remove(){if(!this.tooltip){return}this.tooltip.parentNode.removeChild(this.tooltip);this.tooltip=null};var Resolver=function Resolver(doh_server){this.doh_server=doh_server};Resolver.prototype.lookup=function lookup(type,name,callback){var req=new XMLHttpRequest;req.open("GET",this.doh_server+"?name="+encodeURIComponent(name)+"&type="+encodeURIComponent(type),true);req.setRequestHeader("accept","application/dns-json");req.addEventListener("load",function(event){try{var results=JSON.parse(req.responseText)}catch(error){callback(null,error);return}callback(results,null)});req.addEventListener("error",function(event){callback(null,new Error("DNS Error"))});req.send()};var Validator=function Validator(doh_server){this.doh_server=new Resolver(doh_server)};Validator.prototype.verify=function verify(data,completion_func){var resolver=this.doh_server;var last_at=data.email.lastIndexOf("@");var domain=data.email.substring(last_at+1);var username=data.email.substring(0,last_at);resolver.lookup("MX",domain,function(results,error){if(!results&&error){completion_func({status:"ERROR",message:String(error)});return}if(results.Answer&&results.Answer.length>0){completion_func({status:"GOOD"})}else{resolver.lookup("A",domain,function(a_results,a_error){if(!a_results&&a_error){completion_func({status:"ERROR",message:String(a_error)});return}if(a_results.Answer&&a_results.Answer.length>0){completion_func({status:"GOOD"})}else{completion_func({status:"BAD",message:"Invalid Domain"})}})}})};var options_hash={form_key:"string",manual:"boolean",email_field:"DOMNode",form:"DOMNodeOrBoolean",submit_button:"DOMNodeOrArrayOfDOMNodes",debug:"boolean",onGood:"function",onBad:"function",onChallenge:"function",onError:"function",visuals:"booleanOrVisualsObj",timeout:"number",doh_json_server:"string"};var visuals_all_on={good:true,bad:true,challenge:true};var visuals_all_off={good:false,bad:false,challenge:false};var Form=function Form(options){log.debug("Invoking Class constructor!");log.debugdir(options);for(var key in options){log.debug("Setting: "+key+" to "+options[key]);if(!this.unwrap_assign(key,options[key])){return false}}if(!this.doh_json_server){this.doh_json_server="https://cloudflare-dns.com/dns-query"}this.doh_server=new Validator(this.doh_json_server);if(!this.timeout){this.timeout=15e3}else{this.timeout=1e3*this.timeout}if(this.manual){log.debug("Manual mode selected; exiting setup");return}if(!this.email_field){return log.error("No Email Field set!")}if(typeof this.form=="undefined"||this.form===true){log.debug("Trying to guess Form value");this.form=this.email_field.form;log.debug("Picked: "+this.form)}if(!this.form&&this.form!==false){return log.error("Could not determine Form!")}if(this.form&&!this.submit_button&&this.submit_button!==false){log.debug("Trying to find submit buttons...");var submit_buttons=[];for(var i=0;i1){if(!multiple){log.error("Too many elements found in jQuery selector for "+name+" (count: "+element.length+")");return false}var unwrapped=[];for(var i=0;i")+", and its source: "+(element&&element["prototype"]&&element["prototype"]["toSource"]?element.prototype.toSource():""));return false};Form.prototype.initialize_dom=function initialize_dom(){var this$1=this;var old_onchange=this.email_field.onchange;this.email_field.onchange=function(event){this$1.onchange_handler(event);if(old_onchange){old_onchange(event)}};if(this.form){var old_onsubmit=this.form.onsubmit;this.form.onsubmit=function(event){log.debug("On Submit handler firing!");var results;if(old_onsubmit){results=old_onsubmit(event)}if(!old_onsubmit||results){return this$1.onsubmit_handler(event)}}}this.disable_submits()};Form.prototype.disable_submits=function disable_submits(){this.set_submit_button_disabled(true)};Form.prototype.enable_submits=function enable_submits(){this.set_submit_button_disabled(false)};Form.prototype.set_submit_button_disabled=function set_submit_button_disabled(state){this.submittable=!state;if(this.submit_button){log.debug("Trying to disable submit button...");if(is_array(this.submit_button)){log.debug("Submit button IS ARRAY");for(var x in this.submit_button){this.submit_button[x].disabled=state}}else{this.submit_button.disabled=state}}};Form.prototype.parse_event_handler_results=function parse_event_handler_results(result,behavior,visuals,allow_func,params){var this$1=this;if(typeof result==="undefined"){behavior.apply(void 0,params);visuals.apply(void 0,params);return}else if(result===false){return true}else if(result===true){return behavior.apply(void 0,params)}else if(is_function(result)){if(allow_func){return result(function(nested_function_result){return this$1.parse_event_handler_results(nested_function_result,behavior,visuals,false,params)})}else{log.error("Function type returned when function is not allowed.")}}else{log.error("Unknown type returned from handler '"+typeof result+"'")}};Form.prototype.fire_hooks=function fire_hooks(name,behavior,visuals){var ref;var params=[],len=arguments.length-3;while(len-- >0)params[len]=arguments[len+3];log.debug("Firing hooks for: "+name);if(this.manual){return}if(!this[name]){behavior.apply(void 0,params);visuals.apply(void 0,params);return}var tmp=(ref=this)[name].apply(ref,params);return this.parse_event_handler_results(tmp,behavior,visuals,true,params)};Form.prototype.onchange_handler=function onchange_handler(){this.disable_submits();this.verifying=this.email_field.value;if(this.verifying==""){return}this.verify(this.email_field.value,function(results){log.debug("Verification results are: ");log.debugdir(results)})};Form.prototype.onbad_handler=function onbad_handler(detailed_status,message){var this$1=this;this.fire_hooks("onBad",function(){this$1.disable_submits()},function(){if(this$1.visuals.bad){this$1.tooltip.show(message)}},detailed_status,message)};Form.prototype.ongood_handler=function ongood_handler(detailed_status,checksum,message){var this$1=this;this.fire_hooks("onGood",function(){if(this$1.form){update_hidden_fields(this$1.form,checksum,status)}this$1.enable_submits()},function(){if(this$1.visuals.good){this$1.tooltip.hide()}},detailed_status,message)};Form.prototype.onchallenge_handler=function onchallenge_handler(challenge_key,message){var this$1=this;this.fire_hooks("onChallenge",function(){this$1.disable_submits()},function(){if(!this$1.visuals.challenge){return}this$1.modal.show(challenge_key,message,function(){if(this$1.email_field.value!=this$1.modal.get_challenge_address()){log.debug("Field value: "+this$1.email_field.value+" , challenge_address: "+this$1.modal.get_challenge_address());this$1.modal.bad_address();return}this$1.challenge(this$1.email_field.value,challenge_key,function(results){log.debug("Challenge results are: ");log.debugdir(results);if(results.status=="ACCEPTED"){this$1.modal.pin_input();this$1.modal.set_modal_action(function(){var pin=this$1.modal.get_pin_code();this$1.response(this$1.email_field.value,challenge_key,pin,function(response){log.debugdir(response);if(response.status=="GOOD"){this$1.modal.hide();this$1.ongood_handler(response.status,response.checksum)}else{this$1.modal.bad_pin()}})})}else{window.alert("Challenge rejected!")}})})})};Form.prototype.onerror_handler=function onerror_handler(){var this$1=this;this.fire_hooks("onError",function(){log.debug("Error detected?");this$1.tooltip.remove();this$1.enable_submits()},function(){log.debug("No default visuals for error?")})};Form.prototype.onsubmit_handler=function onsubmit_handler(event){var this$1=this;if(this.submittable&&this.email_field.value===this.verifying){return true}log.debug("Cannot submit form - submittable? "+this.submittable+" our field value? "+this.email_field.value+" what we're verifying? "+this.verifying);if(this.email_field.value!==this.verifying){log.debug("sending new verification!");this.verify(this.email_field.value,function(results){if(this$1.submittable&&this$1.form){this$1.form.submit()}})}return false};Form.prototype.jsp=function jsp(url,data,complete){data.form_key=this.form_key;var timed_out=false;var to=window.setTimeout(function(){timed_out=true;return complete({status:"ERROR",message:"Timeout"})},this.timeout);var completion_handler=function(data){if(timed_out){return}window.clearTimeout(to);return complete(data)};if(!this.form_key){this.doh_server.verify(data,completion_handler)}else{jsonp({url:HOST+"/"+url,data:data,success:completion_handler,error:function(){return completion_handler({status:"ERROR",message:"Server Error"})}})}};Form.prototype.verify=function verify(email,callback){var this$1=this;log.debug("VERIFY low-level method invoked!");this.jsp("verify",{email:email},function(data){if(data.error){log.error(data.error)}var detailed_status=null;if(data&&data.checksum){detailed_status=data.checksum.split(";")[2]}switch(data.status){case"BAD":this$1.onbad_handler(detailed_status,data.message);break;case"GOOD":this$1.ongood_handler(detailed_status,data.checksum,data.message);break;case"CHALLENGE":this$1.onchallenge_handler(data.challenge_key,data.message);break;case"ERROR":this$1.onerror_handler(data.message);break;default:log.error("UNKNOWN STATUS: "+data.status);this$1.onerror_handler(data.message)}if(callback){callback(data)}})};Form.prototype.challenge=function challenge(email,challenge_key,callback){this.jsp("challenge",{email:email,challenge_key:challenge_key},function(data){callback(data)})};Form.prototype.response=function response(email,challenge_key,pin,callback){this.jsp("response",{email:email,challenge_key:challenge_key,pin:pin},function(data){callback(data)})};function auto(options){var activated_forms=[];for(var form=0;form')+", and its source: "+(element && element['prototype'] && element['prototype']['toSource'] ? element.prototype.toSource() : '')) + log.error("Unknown element type passed for "+name+": "+typeof(element)+", and its prototype is: "+(element['prototype'] ? element.prototype : '')+", and its source: "+(element && element['prototype'] && element['prototype']['toSource'] ? element.prototype.toSource() : '')) return false } @@ -228,7 +238,7 @@ export default class Form { if(this.form) { let old_onsubmit = this.form.onsubmit this.form.onsubmit = (event) => { - log.debug("On Submit handler firing!") + log.verbose("On Submit handler firing!") var results if(old_onsubmit) { results = old_onsubmit(event) //TODO - confusing, *their* old onsubmit handler fires *first*? @@ -254,9 +264,9 @@ export default class Form { set_submit_button_disabled(state) { this.submittable = !state // if disabled == true, submittable = false; if disabled == false, submittable = true if(this.submit_button) { - log.debug("Trying to disable submit button...") + log.verbose("Trying to disable submit button...") if(is_array(this.submit_button)) { - log.debug("Submit button IS ARRAY") + log.verbose("Submit button IS ARRAY") for(let x in this.submit_button) { this.submit_button[x].disabled = state } @@ -295,7 +305,7 @@ export default class Form { } fire_hooks(name, behavior, visuals, ...params) { - log.debug("Firing hooks for: "+name) + log.verbose("Firing hooks for: "+name) if(this.manual) { return } @@ -370,8 +380,8 @@ export default class Form { return } this.challenge(this.email_field.value, challenge_key, (results) => { - log.debug("Challenge results are: ") - log.debugdir(results) + log.verbose("Challenge results are: ") + log.verbosedir(results) if(results.status == "ACCEPTED") { this.modal.pin_input() this.modal.set_modal_action( () => { @@ -386,7 +396,7 @@ export default class Form { * their hooks fire correctly. But also, we *do* want to update the checksums and all the * other default behavior of a 'good' verification */ - this.ongood_handler(response.status, response.checksum) + this.ongood_handler(response.status, response.checksum) //FIXME - that's supposed to be a 'detailed status' - not just GOOD } else { this.modal.bad_pin() } @@ -417,9 +427,9 @@ export default class Form { if(this.submittable && this.email_field.value === this.verifying) { return true } - log.debug("Cannot submit form - submittable? "+this.submittable+" our field value? "+this.email_field.value+" what we're verifying? "+this.verifying) + log.verbose("Cannot submit form - submittable? "+this.submittable+" our field value? "+this.email_field.value+" what we're verifying? "+this.verifying) if(this.email_field.value !== this.verifying) { - log.debug("sending new verification!") + log.verbose("sending new verification!") this.verify(this.email_field.value, (results) => { //FIXME - this could double-verify! if(this.submittable && this.form) { //don't directly inspect 'results', assume the onBlah handlers will update 'submittable' this.form.submit() @@ -470,14 +480,14 @@ export default class Form { } verify(email, callback) { - log.debug("VERIFY low-level method invoked!") + log.verbose("VERIFY low-level method invoked!") this.jsp("verify", {email: email}, (data) => { if(data.error) { //out-of-band type of error, or does this *never* fire? log.error(data.error) } let detailed_status = null - if(data && data.checksum) { + if(data && data.checksum) { // FIXME - grabbing detailed status via SPLIT detailed_status = data.checksum.split(";")[2] //what happens if there's a semicolon in the email? Well, it's gonna mess up. } diff --git a/index.js b/index.js index 291f7c8..deed424 100644 --- a/index.js +++ b/index.js @@ -5,7 +5,10 @@ import { duplicate } from "./utils.js" export default function (form_key, options) { - log.debug("MAIN INIT ROUTINE RUNNING!") + if(options.debug) { + log.debug_enabled = options.debug + } + log.verbose("MAIN INIT ROUTINE RUNNING!") if(typeof options === 'undefined') { // handle either Goodforms({blah:'blah',blah:'blah'}) // or Goodforms() @@ -15,14 +18,11 @@ export default function (form_key, options) { if(!options) { options = {} } - if(options.debug) { - log.debug_enabled = options.debug - } if(!form_key && (!options['form_key'])) { log.debug('Form key was not set (root-level)') } log.debug("CREATING NEW FORM WITH FORMKEY: "+form_key) - log.debugdir(options) + log.verbosedir(options) //FIXME - verbosedir? let my_opts = duplicate(options) // if form_key was passed as part of the options, don't try and set it // but if it wasn't, and you don't even *have* a form key - you should also try not to set it. @@ -31,7 +31,7 @@ export default function (form_key, options) { } if(!options.email_field && !options.manual) { log.debug("Engaging 'auto' - ") - log.debugdir(my_opts) + log.verbosedir(my_opts) return auto(my_opts) } return new Form(my_opts) diff --git a/logging.js b/logging.js index 21b55a5..b5eb9a8 100644 --- a/logging.js +++ b/logging.js @@ -10,7 +10,17 @@ class Log { } debug(msg) { - if(this.debug_enabled) { + // 'debug' messages show as debug when debug_enabled is just 'true' + // 'but show as 'info' if debug_enabled is 'verbose' + if(this.debug_enabled === "verbose") { + this.log_at_level('info',msg) + } else if(this.debug_enabled) { + this.log_at_level('debug',msg) + } + } + + verbose(msg) { + if(this.debug_enabled === "verbose") { this.log_at_level('debug',msg) } } @@ -25,6 +35,16 @@ class Log { } } + verbosedir(msg) { + if(this.debug_enabled === "verbose") { + if(typeof console !== "undefined" && console["dir"]) { + this.log_at_level('dir',msg) + } else { + this.log_at_level('debug',msg) + } + } + } + log_at_level(level,msg) { if(typeof console !== "undefined" && console[level]) { console[level](msg) diff --git a/visuals.js b/visuals.js index 882d24a..21dde4b 100644 --- a/visuals.js +++ b/visuals.js @@ -129,7 +129,7 @@ export class modal { } get_modal(challenge_key) { //TODO - this needs breaking up, it's a little rambly - log.debug("Getting modal - challenge key is: "+challenge_key) + log.verbose("Getting modal - challenge key is: "+challenge_key) if(!this.modal) { //TODO prolly need to rename all of these classes to something unique @@ -203,9 +203,9 @@ export class modal { MicroModal.show('goodforms-modal',{ debugMode: true, awaitCloseAnimation: true, - onShow: modal => log.debug(`${modal.id} is shown`), + onShow: modal => log.verbose(`${modal.id} is shown`), onClose: modal => { - log.debug(`${modal.id} is hidden`) + log.verbose(`${modal.id} is hidden`) if(this.modal) { document.body.removeChild(this.modal) delete this.modal