1function getKashooApiBaseUrl() { 2 return 'https://api.kashoo.com/api' 3} 4 5function getKashooAppBaseUrl() { 6 return 'https://app.kashoo.com' 7} 8 9function kashooRemotePost(formId, feedbackId) { 10 var form = jQuery('#' + formId); 11 var feedback = jQuery('#' + feedbackId); 12 bindForm(form, feedback); 13} 14 15/* 16 * This function will find all forms with "formClass" and binds remote post 17 * magic to it. Note: unlike kashooRemotePost, an HTML element with a class of 18 * "feedback" is expected to be nested somewhere inside the form for displaying error messages. 19 */ 20function bootstrapRemotePost(formClass) { 21 let forms = jQuery(document).find('.' + formClass); 22 forms.each(function(idx, rawForm) { 23 let form = jQuery(rawForm); 24 let feedback = form.find('.remote-post-feedback'); 25 bindForm(form, feedback); 26 }); 27} 28 29/* 30 * This version of bootstrap function handles dynamically created forms to guard 31 * against some website optimizers that manipulate and/or re-create forms dynamically. 32 */ 33function bootstrapDynamicRemotePost(formClass) { 34 let formSelector = '.' + formClass; 35 jQuery(document).on('submit', formSelector, null, function(event) { 36 let form = jQuery(this); 37 let feedback = form.find('.remote-post-feedback'); 38 submitForm(event, form, feedback); 39 return false; 40 }); 41} 42 43/* 44 * Bind remote post magic to the given form and feedback elements. 45 */ 46function bindForm(form, feedback) { 47 48 populateForm(form); 49 form.submit(function(event) { 50 submitForm(event, form, feedback); 51 }); 52} 53 54function submitForm(event, form, feedback) { 55 event.preventDefault(); 56 feedback.hide(); 57 58 var url = form.attr('action') || getKashooApiBaseUrl() + '/users/api_signup'; 59 var email = getValue(form, '', 'email'); 60 var password = getValue(form, '', 'password'); 61 var firstName = getValue(form, '', 'firstName'); 62 var lastName = getValue(form, '', 'lastName'); 63 var phoneNumber = getValue(form, '', 'phoneNumber'); 64 var countryCode = getValue(form, '', 'country'); 65 var site = getValue(form, 'app.kashoo.com', 'site'); 66 var inviteCode = getValue(form, '', 'invite'); 67 var campaign = getValue(form, '', 'campaign'); 68 var referral = getValue(form, '', 'ref'); 69 var appsumoCode = getValue(form, false, 'appsumoCode'); 70 var partnerShortCode = getValue(form, '', 'partnerShortCode'); 71 var partnerCustomerId = getValue(form, '', 'partnerCustomerId'); 72 var legacy = getValue(form, '', 'legacy'); // non-blank value will create business in books 73 var termsOfServiceAccepted = form.find('input[name="termsOfService"]').is(':checked') || false; 74 const signupParams = { email, password, firstName, lastName, phoneNumber, countryCode, site, inviteCode, campaign, referral, appsumoCode, partnerShortCode, partnerCustomerId, termsOfServiceAccepted, legacy } 75 76 let validateDeferred = validateForm(signupParams) 77 jQuery.when(validateDeferred) 78 .done(function() { 79 callSignupApi(url, signupParams, feedback) 80 }) 81 .fail(function(reason) { 82 feedback.empty().append(reason) 83 feedback.show() 84 }); 85} 86 87function checkAppsumoSignup(signupParams) { 88 return signupParams.appsumoCode !== false 89} 90 91function callSignupApi(url, signupParams, feedback) { 92 93 // :see-no-evil: 94 const isAppsumoSignup = checkAppsumoSignup(signupParams) 95 const referral = isAppsumoSignup ? signupParams.appsumoCode : signupParams.referral; 96 97 var additionalParams = { 98 "countryCode": signupParams.countryCode, 99 "phone": signupParams.phoneNumber, 100 "invite": signupParams.inviteCode, 101 "campaign": signupParams.campaign, 102 "referral": referral, 103 "termsOfServiceAccepted": signupParams.termsOfServiceAccepted 104 }; 105 106 var posting = jQuery.post(url, { 107 first: signupParams.firstName, 108 last: signupParams.lastName, 109 email: signupParams.email, 110 password: signupParams.password, 111 site: signupParams.site, 112 additionalParams: JSON.stringify(additionalParams) 113 }); 114 115 posting 116 .done(function(data) { 117 // at this point user account has been created 118 let appsumoDeferred = jQuery.Deferred() 119 jQuery.when(appsumoDeferred).done(function() { 120 signupApiSuccess(data, signupParams, feedback) 121 }) 122 123 if (isAppsumoSignup) { 124 redeemAppSumoCode(signupParams.appsumoCode, appsumoDeferred) 125 } else { 126 appsumoDeferred.resolve() // no need to redeem, ok to resolve now 127 } 128 }) 129 .fail(function(data, textStatus, errorThrown) { 130 signupApiFailed(data, textStatus, errorThrown, feedback) 131 }); 132} 133 134function validateAppSumoCode(appsumoCode, deferred) { 135
136 // check for blank appsumo code first before sending over to API for verification. otherwise API will return an 404 137 if (appsumoCode == '') { 138 deferred.reject('Please enter AppSumo code') 139 return 140 } 141 142 let url = getKashooApiBaseUrl() + '/appsumo/verify/' + appsumoCode 143 jQuery.get(url) 144 .done(function(data) { 145 let result = JSON.parse(JSON.stringify(data)) 146 if (result.status == 1) { 147 deferred.resolve() 148 } else { 149 let friendlyReason = result.reason 150 switch (result.status) { 151 case 2: 152 friendlyReason = 'The code "' + appsumoCode + '" has already been used.' 153 break; 154 case 3: 155 friendlyReason = 'The code "' + appsumoCode + '" is invalid.' 156 break; 157 case 4: 158 friendlyReason = 'The code cannot be verified at the moment. Please try again later.' 159 break; 160 } 161 deferred.reject(friendlyReason) 162 } 163 }) 164 .fail(function(data) { 165 // TODO add RUM here 166 deferred.reject() 167 }) 168} 169 170function redeemAppSumoCode(appsumoCode, deferred) { 171 let url = getKashooApiBaseUrl() + '/appsumo/redeem/' + appsumoCode 172 jQuery.get(url) 173 .done(function(data) { 174 console.log('Redeemed code!') 175 }) 176 .fail(function(data) { 177 console.log('Failed to redeem code') 178 }) 179 .always(function() { 180 deferred.resolve() 181 }); 182} 183 184function validateForm(signupParams) { 185 let deferred = jQuery.Deferred() 186 if (!signupParams.termsOfServiceAccepted) { 187 deferred.reject('Please accept our terms of service before continuing.') 188 } else if (checkAppsumoSignup(signupParams)) { 189 validateAppSumoCode(signupParams.appsumoCode, deferred) 190 } else { 191 deferred.resolve() 192 } 193 return deferred 194} 195 196function signupApiSuccess(data, signupParams, feedback) { 197 var parsedData = JSON.parse(JSON.stringify(data)); 198 //if the server is set to do direct login (without email validation) 199 if (parsedData.status == 200) { 200 window.location.href = getKashooAppBaseUrl() + "/sign-up-success" 201 } else if (signupParams.legacy && parsedData.status == 201) { 202 window.location.href = getKashooAppBaseUrl() + "/app?licensePartner.shortCode=" + signupParams.partnerShortCode + "&licensePartner.customerIdentifier=" + signupParams.partnerCustomerId + "&auth=" + parsedData.responseText; 203 } else if (parsedData.status == 201) { 204 window.location.href = getKashooAppBaseUrl() + "/tsb/setup/business?auth=" + parsedData.responseText + '&licensePartner.shortCode=' + signupParams.partnerShortCode + "&licensePartner.customerIdentifier=" + signupParams.partnerCustomerId; 205 } else { 206 feedback.show(); 207 } 208} 209 210function signupApiFailed(data, textStatus, errorThrown, feedback) { 211 feedback.show(); 212 var parsedData = JSON.parse(data.responseText) 213 if (parsedData.status === '409') { 214 parsedData.responseText = parsedData.responseText + ' | <a href="https://app.kashoo.com/app/reset-password" target="_blank">Reset Password</a>' 215 } 216 feedback.empty().append("<p>" + parsedData.responseText + "</p>"); 217} 218 219/** 220 * Populate form with values in query string. 221 */ 222function populateForm(form) { 223 populateFormField(form, 'firstName', 'first', 'firstName'); 224 populateFormField(form, 'lastName', 'last', 'lastName'); 225 populateFormField(form, 'email', 'email', undefined); 226 populateFormField(form, 'phoneNumber', 'phone', 'phoneNumber'); 227 populateFormField(form, 'ref', 'referrer', 'ref'); 228 populateFormField(form, 'campaign', 'campaign', undefined); 229 populateFormField(form, 'partnerShortCode', 'partnerShortCode', undefined); 230 populateFormField(form, 'partnerCustomerId', 'partnerCustomerID', 'partnerCustomerId'); 231} 232 233function populateFormField(form, inputName, parameterName1, parameterName2) { 234 var parameterValue = getUrlParameter(parameterName1) || getUrlParameter(parameterName2); 235 if (parameterValue) { 236 var target = 'input[name="' + inputName + '"]'; 237 var input = form.find(target); 238 if (input) { 239 input.val(parameterValue); 240 } 241 } 242} 243 244function getValue(form, defaultValue, inputName) { 245 var inputField = form.find('input[name="' + inputName + '"]'); 246 var inputValue = inputField ? inputField.val() : undefined; 247 var v = inputValue !== undefined ? inputValue : defaultValue; 248 return v; 249} 250 251function getUrlParameter(sParam) { 252 var sPageURL = decodeURIComponent(window.location.search.substring(1)), 253 sURLVariables = sPageURL.split('&'), 254 sParameterName, 255 i; 256 257 for (i = 0; i < sURLVariables.length; i++) { 258 sParameterName = sURLVariables[i].split('='); 259 260 if (sParameterName[0] === sParam) { 261 return sParameterName[1] === undefined ? true : sParameterName[1]; 262 } 263 } 264} 265 266jQuery(document).ready(function() { 267 //bootstrapRemotePost('remote-post-form'); 268 bootstrapDynamicRemotePost('remote-post-form'); 269});
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.