form.js 86 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069
  1. /*============================================
  2. Conditional Logic
  3. ==============================================*/
  4. var __gf_timeout_handle;
  5. function gf_apply_rules(formId, fields, isInit){
  6. var rule_applied = 0;
  7. for(var i=0; i < fields.length; i++){
  8. gf_apply_field_rule(formId, fields[i], isInit, function(){
  9. rule_applied++;
  10. if(rule_applied == fields.length){
  11. jQuery(document).trigger('gform_post_conditional_logic', [formId, fields, isInit]);
  12. if(window["gformCalculateTotalPrice"])
  13. window["gformCalculateTotalPrice"](formId);
  14. }
  15. });
  16. }
  17. }
  18. function gf_check_field_rule(formId, fieldId, isInit, callback){
  19. //if conditional logic is not specified for that field, it is supposed to be displayed
  20. if(!window["gf_form_conditional_logic"] || !window["gf_form_conditional_logic"][formId] || !window["gf_form_conditional_logic"][formId]["logic"][fieldId])
  21. return "show";
  22. var conditionalLogic = window["gf_form_conditional_logic"][formId]["logic"][fieldId];
  23. var action = gf_get_field_action(formId, conditionalLogic["section"]);
  24. //If section is hidden, always hide field. If section is displayed, see if field is supposed to be displayed or hidden
  25. if(action != "hide")
  26. action = gf_get_field_action(formId, conditionalLogic["field"]);
  27. return action;
  28. }
  29. function gf_apply_field_rule(formId, fieldId, isInit, callback){
  30. var action = gf_check_field_rule(formId, fieldId, isInit, callback);
  31. gf_do_field_action(formId, action, fieldId, isInit, callback);
  32. var conditionalLogic = window["gf_form_conditional_logic"][formId]["logic"][fieldId];
  33. //perform conditional logic for the next button
  34. if(conditionalLogic["nextButton"]){
  35. action = gf_get_field_action(formId, conditionalLogic["nextButton"]);
  36. gf_do_next_button_action(formId, action, fieldId, isInit);
  37. }
  38. }
  39. function gf_get_field_action(formId, conditionalLogic){
  40. if(!conditionalLogic)
  41. return "show";
  42. var matches = 0;
  43. for(var i = 0; i < conditionalLogic["rules"].length; i++){
  44. var rule = conditionalLogic["rules"][i];
  45. if(gf_is_match(formId, rule))
  46. matches++;
  47. }
  48. var action;
  49. if( (conditionalLogic["logicType"] == "all" && matches == conditionalLogic["rules"].length) || (conditionalLogic["logicType"] == "any" && matches > 0) )
  50. action = conditionalLogic["actionType"];
  51. else
  52. action = conditionalLogic["actionType"] == "show" ? "hide" : "show";
  53. return action;
  54. }
  55. function gf_is_match(formId, rule){
  56. var isMatch = false;
  57. var inputs = jQuery("#input_" + formId + "_" + rule["fieldId"] + " input");
  58. var fieldValue;
  59. if(inputs.length > 0){
  60. //handling checkboxes/radio
  61. for(var i=0; i< inputs.length; i++){
  62. fieldValue = gf_get_value(jQuery(inputs[i]).val());
  63. //find specific checkbox/radio item. Skip if this is not the specific item and the operator is not one that targets a range of values (i.e. greater than and less than)
  64. var isRangeOperator = jQuery.inArray(rule["operator"], ["<", ">", "contains", "starts_with", "ends_with"]) >= 0;
  65. if(fieldValue != rule["value"] && !isRangeOperator) {
  66. continue;
  67. }
  68. //blank value if item isn't checked
  69. if(!jQuery(inputs[i]).is(":checked")) {
  70. fieldValue = "";
  71. }
  72. else if (fieldValue == "gf_other_choice"){
  73. //get the value from the associated text box
  74. fieldValue = jQuery("#input_" + formId + "_" + rule["fieldId"] + "_other").val();
  75. }
  76. if(gf_matches_operation(fieldValue, rule["value"], rule["operator"]))
  77. isMatch = true;
  78. }
  79. }
  80. else{
  81. //handling all other fields (non-checkboxes)
  82. var val = jQuery("#input_" + formId + "_" + rule["fieldId"]).val();
  83. //transform regular value into array to support multi-select (which returns an array of selected items)
  84. var values = (val instanceof Array) ? val : [val];
  85. var matchCount = 0;
  86. var fieldNumberFormat = window['gf_global'] && gf_global.number_formats && gf_global.number_formats[formId] && gf_global.number_formats[formId][rule["fieldId"]] ? gf_global.number_formats[formId][rule["fieldId"]] : false;
  87. for(var i=0; i < values.length; i++){
  88. //fields with pipes in the value will use the label for conditional logic comparison
  89. var hasLabel = values[i] ? values[i].indexOf("|") >= 0 : true;
  90. fieldValue = gf_get_value(values[i]);
  91. var decimalSeparator = ".";
  92. if( fieldNumberFormat && !hasLabel){
  93. if( fieldNumberFormat == "currency" )
  94. decimalSeparator = gformGetDecimalSeparator('currency');
  95. else if( fieldNumberFormat == "decimal_comma")
  96. decimalSeparator = ",";
  97. else if( fieldNumberFormat == "decimal_dot")
  98. decimalSeparator = ".";
  99. //transform to a decimal dot number
  100. fieldValue = gformCleanNumber( fieldValue, '', '', decimalSeparator);
  101. //now transform to number specified by locale
  102. if(window['gf_number_format'] && window['gf_number_format'] == "decimal_comma")
  103. fieldValue = gformFormatNumber(fieldValue, -1, ",", ".");
  104. if( ! fieldValue )
  105. fieldValue = 0;
  106. fieldValue = fieldValue.toString();
  107. }
  108. if(gf_matches_operation(fieldValue, rule["value"], rule["operator"])){
  109. matchCount++;
  110. }
  111. }
  112. //If operator is Is Not, none of the value can match
  113. isMatch = rule["operator"] == "isnot" ? matchCount == values.length : matchCount > 0;
  114. }
  115. return gform.applyFilters( 'gform_is_value_match', isMatch, formId, rule );
  116. }
  117. function gf_try_convert_float(text){
  118. var format = window["gf_number_format"] == "decimal_comma" ? "decimal_comma" : "decimal_dot";
  119. if(gformIsNumeric(text, format)){
  120. var decimal_separator = format == "decimal_comma" ? "," : ".";
  121. return gformCleanNumber(text, "", "", decimal_separator);
  122. }
  123. return text;
  124. }
  125. function gf_matches_operation(val1, val2, operation){
  126. val1 = val1 ? val1.toLowerCase() : "";
  127. val2 = val2 ? val2.toLowerCase() : "";
  128. switch(operation){
  129. case "is" :
  130. return val1 == val2;
  131. break;
  132. case "isnot" :
  133. return val1 != val2;
  134. break;
  135. case ">" :
  136. val1 = gf_try_convert_float(val1);
  137. val2 = gf_try_convert_float(val2);
  138. return gformIsNumber(val1) && gformIsNumber(val2) ? val1 > val2 : false;
  139. break;
  140. case "<" :
  141. val1 = gf_try_convert_float(val1);
  142. val2 = gf_try_convert_float(val2);
  143. return gformIsNumber(val1) && gformIsNumber(val2) ? val1 < val2 : false;
  144. break;
  145. case "contains" :
  146. return val1.indexOf(val2) >=0;
  147. break;
  148. case "starts_with" :
  149. return val1.indexOf(val2) ==0;
  150. break;
  151. case "ends_with" :
  152. var start = val1.length - val2.length;
  153. if(start < 0)
  154. return false;
  155. var tail = val1.substring(start);
  156. return val2 == tail;
  157. break;
  158. }
  159. return false;
  160. }
  161. function gf_get_value(val){
  162. if(!val)
  163. return "";
  164. val = val.split("|");
  165. return val[0];
  166. }
  167. function gf_do_field_action(formId, action, fieldId, isInit, callback){
  168. var conditional_logic = window["gf_form_conditional_logic"][formId];
  169. var dependent_fields = conditional_logic["dependents"][fieldId];
  170. for(var i=0; i < dependent_fields.length; i++){
  171. var targetId = fieldId == 0 ? "#gform_submit_button_" + formId : "#field_" + formId + "_" + dependent_fields[i];
  172. //calling callback function on the last dependent field, to make sure it is only called once
  173. do_callback = (i+1) == dependent_fields.length ? callback : null;
  174. gf_do_action(action, targetId, conditional_logic["animation"], conditional_logic["defaults"][dependent_fields[i]], isInit, do_callback);
  175. }
  176. }
  177. function gf_do_next_button_action(formId, action, fieldId, isInit){
  178. var conditional_logic = window["gf_form_conditional_logic"][formId];
  179. var targetId = "#gform_next_button_" + formId + "_" + fieldId;
  180. gf_do_action(action, targetId, conditional_logic["animation"], null, isInit);
  181. }
  182. function gf_do_action(action, targetId, useAnimation, defaultValues, isInit, callback){
  183. var $target = jQuery(targetId);
  184. if(action == "show"){
  185. if(useAnimation && !isInit){
  186. if($target.length > 0){
  187. $target.slideDown(callback);
  188. } else if(callback){
  189. callback();
  190. }
  191. }
  192. else{
  193. //$target.show();
  194. //Getting around an issue with Chrome on Android. Does not like jQuery('xx').show() ...
  195. $target.css('display', 'block');
  196. if(callback){
  197. callback();
  198. }
  199. }
  200. }
  201. else{
  202. //if field is not already hidden, reset its values to the default
  203. var child = $target.children().first();
  204. if (child.length > 0){
  205. if(!gformIsHidden(child)){
  206. gf_reset_to_default(targetId, defaultValues);
  207. }
  208. }
  209. if(useAnimation && !isInit){
  210. if($target.length > 0 && $target.is(":visible")) {
  211. $target.slideUp(callback);
  212. } else if(callback) {
  213. callback();
  214. }
  215. } else{
  216. $target.hide();
  217. if(callback){
  218. callback();
  219. }
  220. }
  221. }
  222. }
  223. function gf_reset_to_default(targetId, defaultValue){
  224. var dateFields = jQuery(targetId).find('.gfield_date_month input[type="text"], .gfield_date_day input[type="text"], .gfield_date_year input[type="text"], .gfield_date_dropdown_month select, .gfield_date_dropdown_day select, .gfield_date_dropdown_year select');
  225. var dateIndex = 0;
  226. if(dateFields.length > 0){
  227. dateFields.each(function(){
  228. if(defaultValue){
  229. val = defaultValue.split(/[\.\/-]+/)[dateIndex];
  230. dateIndex++;
  231. }
  232. else{
  233. val = "";
  234. }
  235. var element = jQuery(this);
  236. if(element.prop("tagName") == "SELECT")
  237. val = parseInt(val);
  238. if(element.val() != val)
  239. element.val(val).trigger("change");
  240. else
  241. element.val(val);
  242. });
  243. return;
  244. }
  245. //cascading down conditional logic to children to suppport nested conditions
  246. //text fields and drop downs
  247. var target = jQuery(targetId).find('select, input[type="text"], input[type="number"], textarea');
  248. var target_index = 0;
  249. target.each(function(){
  250. var val = "";
  251. var element = jQuery(this);
  252. if(element.is('select:not([multiple])')){
  253. val = element.find('option' ).not( ':disabled' ).eq(0).val();
  254. }
  255. //get name of previous input field to see if it is the radio button which goes with the "Other" text box
  256. //otherwise field is populated with input field name
  257. var radio_button_name = element.prev("input").attr("value");
  258. if(radio_button_name == "gf_other_choice"){
  259. val = element.attr("value");
  260. }
  261. else if(jQuery.isArray(defaultValue)){
  262. val = defaultValue[target_index];
  263. }
  264. else if(jQuery.isPlainObject(defaultValue)){
  265. val = defaultValue[element.attr("name")];
  266. }
  267. else if(defaultValue){
  268. val = defaultValue;
  269. }
  270. if(element.val() != val)
  271. element.val(val).trigger('change');
  272. else
  273. element.val(val);
  274. target_index++;
  275. });
  276. //checkboxes and radio buttons
  277. var elements = jQuery(targetId).find('input[type="radio"], input[type="checkbox"]');
  278. elements.each(function(){
  279. //is input currently checked?
  280. var isChecked = jQuery(this).is(':checked') ? true : false;
  281. //does input need to be marked as checked or unchecked?
  282. var doCheck = defaultValue ? jQuery.inArray(jQuery(this).attr('id'), defaultValue) > -1 : false;
  283. //if value changed, trigger click event
  284. if(isChecked != doCheck){
  285. //setting input as checked or unchecked appropriately
  286. if(jQuery(this).attr("type") == "checkbox"){
  287. jQuery(this).trigger('click');
  288. }
  289. else{
  290. jQuery(this).prop("checked", doCheck);
  291. //need to set the prop again after the click is triggered
  292. jQuery(this).trigger('click').prop('checked', doCheck);
  293. }
  294. }
  295. });
  296. }
  297. /*============================================
  298. jQuery JSON
  299. ==============================================*/
  300. (function($) {
  301. function toIntegersAtLease(n)
  302. // Format integers to have at least two digits.
  303. {
  304. return n < 10 ? '0' + n : n;
  305. }
  306. Date.prototype.toJSON = function(date)
  307. // Yes, it polutes the Date namespace, but we'll allow it here, as
  308. // it's damned usefull.
  309. {
  310. return this.getUTCFullYear() + '-' +
  311. toIntegersAtLease(this.getUTCMonth()) + '-' +
  312. toIntegersAtLease(this.getUTCDate());
  313. };
  314. var escapeable = /["\\\x00-\x1f\x7f-\x9f]/g;
  315. var meta = { // table of character substitutions
  316. '\b': '\\b',
  317. '\t': '\\t',
  318. '\n': '\\n',
  319. '\f': '\\f',
  320. '\r': '\\r',
  321. '"' : '\\"',
  322. '\\': '\\\\'
  323. };
  324. $.quoteString = function(string)
  325. // Places quotes around a string, inteligently.
  326. // If the string contains no control characters, no quote characters, and no
  327. // backslash characters, then we can safely slap some quotes around it.
  328. // Otherwise we must also replace the offending characters with safe escape
  329. // sequences.
  330. {
  331. //if (escapeable.test(string))
  332. //{
  333. return '"' + string.replace(escapeable, function (a)
  334. {
  335. var c = meta[a];
  336. if (typeof c === 'string') {
  337. return c;
  338. }
  339. c = a.charCodeAt();
  340. return '\\u00' + Math.floor(c / 16).toString(16) + (c % 16).toString(16);
  341. }) + '"';
  342. //}
  343. //else{
  344. // string = string.replace('\n','\\n');
  345. //}
  346. return '"' + string + '"';
  347. };
  348. $.toJSON = function(o, compact)
  349. {
  350. var type = typeof(o);
  351. if (type == "undefined")
  352. return "undefined";
  353. else if (type == "number" || type == "boolean")
  354. return o + "";
  355. else if (o === null)
  356. return "null";
  357. // Is it a string?
  358. if (type == "string")
  359. {
  360. var str = $.quoteString(o);
  361. return str;
  362. }
  363. // Does it have a .toJSON function?
  364. if (type == "object" && typeof o.toJSON == "function")
  365. return o.toJSON(compact);
  366. // Is it an array?
  367. if (type != "function" && typeof(o.length) == "number")
  368. {
  369. var ret = [];
  370. for (var i = 0; i < o.length; i++) {
  371. ret.push( $.toJSON(o[i], compact) );
  372. }
  373. if (compact)
  374. return "[" + ret.join(",") + "]";
  375. else
  376. return "[" + ret.join(", ") + "]";
  377. }
  378. // If it's a function, we have to warn somebody!
  379. if (type == "function") {
  380. throw new TypeError("Unable to convert object of type 'function' to json.");
  381. }
  382. // It's probably an object, then.
  383. var ret = [];
  384. for (var k in o) {
  385. var name;
  386. type = typeof(k);
  387. if (type == "number")
  388. name = '"' + k + '"';
  389. else if (type == "string")
  390. name = $.quoteString(k);
  391. else
  392. continue; //skip non-string or number keys
  393. var val = $.toJSON(o[k], compact);
  394. if (typeof(val) != "string") {
  395. // skip non-serializable values
  396. continue;
  397. }
  398. if (compact)
  399. ret.push(name + ":" + val);
  400. else
  401. ret.push(name + ": " + val);
  402. }
  403. return "{" + ret.join(", ") + "}";
  404. };
  405. $.compactJSON = function(o)
  406. {
  407. return $.toJSON(o, true);
  408. };
  409. $.evalJSON = function(src)
  410. // Evals JSON that we know to be safe.
  411. {
  412. return eval("(" + src + ")");
  413. };
  414. $.secureEvalJSON = function(src)
  415. // Evals JSON in a way that is *more* secure.
  416. {
  417. var filtered = src;
  418. filtered = filtered.replace(/\\["\\\/bfnrtu]/g, '@');
  419. filtered = filtered.replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g, ']');
  420. filtered = filtered.replace(/(?:^|:|,)(?:\s*\[)+/g, '');
  421. if (/^[\],:{}\s]*$/.test(filtered))
  422. return eval("(" + src + ")");
  423. else
  424. throw new SyntaxError("Error parsing JSON, source is not valid.");
  425. };
  426. })(jQuery);
  427. /*============================================
  428. Placeholders.js v2.1.1
  429. ==============================================*/
  430. (function(t){"use strict";function e(t,e,r){return t.addEventListener?t.addEventListener(e,r,!1):t.attachEvent?t.attachEvent("on"+e,r):void 0}function r(t,e){var r,n;for(r=0,n=t.length;n>r;r++)if(t[r]===e)return!0;return!1}function n(t,e){var r;t.createTextRange?(r=t.createTextRange(),r.move("character",e),r.select()):t.selectionStart&&(t.focus(),t.setSelectionRange(e,e))}function a(t,e){try{return t.type=e,!0}catch(r){return!1}}t.Placeholders={Utils:{addEventListener:e,inArray:r,moveCaret:n,changeType:a}}})(this),function(t){"use strict";function e(){}function r(t,e){var r,n,a=!!e&&t.value!==e,u=t.value===t.getAttribute(V);return(a||u)&&"true"===t.getAttribute(D)?(t.setAttribute(D,"false"),t.value=t.value.replace(t.getAttribute(V),""),t.className=t.className.replace(R,""),n=t.getAttribute(z),n&&(t.setAttribute("maxLength",n),t.removeAttribute(z)),r=t.getAttribute(I),r&&(t.type=r),!0):!1}function n(t){var e,r,n=t.getAttribute(V);return""===t.value&&n?(t.setAttribute(D,"true"),t.value=n,t.className+=" "+k,r=t.getAttribute(z),r||(t.setAttribute(z,t.maxLength),t.removeAttribute("maxLength")),e=t.getAttribute(I),e?t.type="text":"password"===t.type&&K.changeType(t,"text")&&t.setAttribute(I,"password"),!0):!1}function a(t,e){var r,n,a,u,i;if(t&&t.getAttribute(V))e(t);else for(r=t?t.getElementsByTagName("input"):p,n=t?t.getElementsByTagName("textarea"):h,i=0,u=r.length+n.length;u>i;i++)a=r.length>i?r[i]:n[i-r.length],e(a)}function u(t){a(t,r)}function i(t){a(t,n)}function l(t){return function(){b&&t.value===t.getAttribute(V)&&"true"===t.getAttribute(D)?K.moveCaret(t,0):r(t)}}function o(t){return function(){n(t)}}function c(t){return function(e){return m=t.value,"true"===t.getAttribute(D)&&m===t.getAttribute(V)&&K.inArray(C,e.keyCode)?(e.preventDefault&&e.preventDefault(),!1):void 0}}function s(t){return function(){r(t,m),""===t.value&&(t.blur(),K.moveCaret(t,0))}}function d(t){return function(){t===document.activeElement&&t.value===t.getAttribute(V)&&"true"===t.getAttribute(D)&&K.moveCaret(t,0)}}function g(t){return function(){u(t)}}function v(t){t.form&&(L=t.form,L.getAttribute(P)||(K.addEventListener(L,"submit",g(L)),L.setAttribute(P,"true"))),K.addEventListener(t,"focus",l(t)),K.addEventListener(t,"blur",o(t)),b&&(K.addEventListener(t,"keydown",c(t)),K.addEventListener(t,"keyup",s(t)),K.addEventListener(t,"click",d(t))),t.setAttribute(U,"true"),t.setAttribute(V,E),n(t)}var p,h,b,f,m,A,y,E,x,L,T,N,S,w=["text","search","url","tel","email","password","number","textarea"],C=[27,33,34,35,36,37,38,39,40,8,46],B="#ccc",k="placeholdersjs",R=RegExp("(?:^|\\s)"+k+"(?!\\S)"),V="data-placeholder-value",D="data-placeholder-active",I="data-placeholder-type",P="data-placeholder-submit",U="data-placeholder-bound",j="data-placeholder-focus",q="data-placeholder-live",z="data-placeholder-maxlength",F=document.createElement("input"),G=document.getElementsByTagName("head")[0],H=document.documentElement,J=t.Placeholders,K=J.Utils;if(J.nativeSupport=void 0!==F.placeholder,!J.nativeSupport){for(p=document.getElementsByTagName("input"),h=document.getElementsByTagName("textarea"),b="false"===H.getAttribute(j),f="false"!==H.getAttribute(q),A=document.createElement("style"),A.type="text/css",y=document.createTextNode("."+k+" { color:"+B+"; }"),A.styleSheet?A.styleSheet.cssText=y.nodeValue:A.appendChild(y),G.insertBefore(A,G.firstChild),S=0,N=p.length+h.length;N>S;S++)T=p.length>S?p[S]:h[S-p.length],E=T.attributes.placeholder,E&&(E=E.nodeValue,E&&K.inArray(w,T.type)&&v(T));x=setInterval(function(){for(S=0,N=p.length+h.length;N>S;S++)T=p.length>S?p[S]:h[S-p.length],E=T.attributes.placeholder,E&&(E=E.nodeValue,E&&K.inArray(w,T.type)&&(T.getAttribute(U)||v(T),(E!==T.getAttribute(V)||"password"===T.type&&!T.getAttribute(I))&&("password"===T.type&&!T.getAttribute(I)&&K.changeType(T,"text")&&T.setAttribute(I,"password"),T.value===T.getAttribute(V)&&(T.value=E),T.setAttribute(V,E))));f||clearInterval(x)},100)}J.disable=J.nativeSupport?e:u,J.enable=J.nativeSupport?e:i}(this);
  431. /*============================================
  432. Gravity Forms
  433. ==============================================*/
  434. // "prop" method fix for previous versions of jQuery (1.5 and below)
  435. if( typeof jQuery.fn.prop === 'undefined' ) {
  436. jQuery.fn.prop = jQuery.fn.attr;
  437. }
  438. //Formatting free form currency fields to currency
  439. jQuery(document).ready(function(){
  440. jQuery(document).bind('gform_post_render', gformBindFormatPricingFields);
  441. });
  442. function gformBindFormatPricingFields(){
  443. jQuery(".ginput_amount, .ginput_donation_amount").bind("change", function(){
  444. gformFormatPricingField(this);
  445. });
  446. jQuery(".ginput_amount, .ginput_donation_amount").each(function(){
  447. gformFormatPricingField(this);
  448. });
  449. }
  450. //------------------------------------------------
  451. //---------- CURRENCY ----------------------------
  452. //------------------------------------------------
  453. function Currency(currency){
  454. this.currency = currency;
  455. this.toNumber = function(text){
  456. if(this.isNumeric(text))
  457. return parseFloat(text);
  458. return gformCleanNumber(text, this.currency["symbol_right"], this.currency["symbol_left"], this.currency["decimal_separator"]);
  459. };
  460. this.toMoney = function(number){
  461. if(!this.isNumeric(number))
  462. number = this.toNumber(number);
  463. if(number === false)
  464. return "";
  465. number = number + "";
  466. negative = "";
  467. if(number[0] == "-"){
  468. negative = "-";
  469. number = parseFloat(number.substr(1));
  470. }
  471. money = this.numberFormat(number, this.currency["decimals"], this.currency["decimal_separator"], this.currency["thousand_separator"]);
  472. var symbol_left = this.currency["symbol_left"] ? this.currency["symbol_left"] + this.currency["symbol_padding"] : "";
  473. var symbol_right = this.currency["symbol_right"] ? this.currency["symbol_padding"] + this.currency["symbol_right"] : "";
  474. money = negative + this.htmlDecode(symbol_left) + money + this.htmlDecode(symbol_right);
  475. return money;
  476. };
  477. this.numberFormat = function(number, decimals, dec_point, thousands_sep, padded){
  478. var padded = typeof padded == 'undefined';
  479. number = (number+'').replace(',', '').replace(' ', '');
  480. var n = !isFinite(+number) ? 0 : +number,
  481. prec = !isFinite(+decimals) ? 0 : Math.abs(decimals),
  482. sep = (typeof thousands_sep === 'undefined') ? ',' : thousands_sep, dec = (typeof dec_point === 'undefined') ? '.' : dec_point,
  483. s = '',
  484. toFixedFix = function (n, prec) {
  485. var k = Math.pow(10, prec);
  486. return '' + Math.round(n * k) / k;
  487. };
  488. if(decimals == '0') {
  489. s = ('' + Math.round(n)).split('.');
  490. } else
  491. if(decimals == -1) {
  492. s = ('' + n).split('.');
  493. } else {
  494. // Fix for IE parseFloat(0.55).toFixed(0) = 0;
  495. s = toFixedFix(n, prec).split('.');
  496. }
  497. if (s[0].length > 3) {
  498. s[0] = s[0].replace(/\B(?=(?:\d{3})+(?!\d))/g, sep);
  499. }
  500. if(padded) {
  501. if ((s[1] || '').length < prec) {
  502. s[1] = s[1] || '';
  503. s[1] += new Array(prec - s[1].length + 1).join('0');
  504. }
  505. }
  506. return s.join(dec);
  507. }
  508. this.isNumeric = function(number){
  509. return gformIsNumber(number);
  510. };
  511. this.htmlDecode = function(text) {
  512. var c,m,d = text;
  513. // look for numerical entities &#34;
  514. var arr=d.match(/&#[0-9]{1,5};/g);
  515. // if no matches found in string then skip
  516. if(arr!=null){
  517. for(var x=0;x<arr.length;x++){
  518. m = arr[x];
  519. c = m.substring(2,m.length-1); //get numeric part which is refernce to unicode character
  520. // if its a valid number we can decode
  521. if(c >= -32768 && c <= 65535){
  522. // decode every single match within string
  523. d = d.replace(m, String.fromCharCode(c));
  524. }else{
  525. d = d.replace(m, ""); //invalid so replace with nada
  526. }
  527. }
  528. }
  529. return d;
  530. };
  531. }
  532. function gformCleanNumber(text, symbol_right, symbol_left, decimal_separator){
  533. //converting to a string if a number as passed
  534. text = text + " ";
  535. //Removing symbol in unicode format (i.e. &#4444;)
  536. text = text.replace(/&.*?;/, "", text);
  537. //Removing symbol from text
  538. text = text.replace(symbol_right, "");
  539. text = text.replace(symbol_left, "");
  540. //Removing all non-numeric characters
  541. var clean_number = "";
  542. var is_negative = false;
  543. for(var i=0; i<text.length; i++){
  544. var digit = text.substr(i,1);
  545. if( (parseInt(digit) >= 0 && parseInt(digit) <= 9) || digit == decimal_separator )
  546. clean_number += digit;
  547. else if(digit == '-')
  548. is_negative = true;
  549. }
  550. //Removing thousand separators but keeping decimal point
  551. var float_number = "";
  552. for(var i=0; i<clean_number.length; i++)
  553. {
  554. var char = clean_number.substr(i,1);
  555. if (char >= '0' && char <= '9')
  556. float_number += char;
  557. else if(char == decimal_separator){
  558. float_number += ".";
  559. }
  560. }
  561. if(is_negative)
  562. float_number = "-" + float_number;
  563. return gformIsNumber(float_number) ? parseFloat(float_number) : false;
  564. }
  565. function gformGetDecimalSeparator(numberFormat){
  566. var s;
  567. switch (numberFormat){
  568. case 'currency' :
  569. var currency = new Currency(gf_global.gf_currency_config);
  570. s = currency.currency["decimal_separator"];
  571. break;
  572. case 'decimal_comma' :
  573. s = ',';
  574. break;
  575. default :
  576. s = "."
  577. }
  578. return s;
  579. }
  580. function gformIsNumber(n) {
  581. return !isNaN(parseFloat(n)) && isFinite(n);
  582. }
  583. function gformIsNumeric(value, number_format){
  584. switch(number_format){
  585. case "decimal_dot" :
  586. var r = new RegExp("^(-?[0-9]{1,3}(?:,?[0-9]{3})*(?:\.[0-9]+)?)$");
  587. return r.test(value);
  588. break;
  589. case "decimal_comma" :
  590. var r = new RegExp("^(-?[0-9]{1,3}(?:\.?[0-9]{3})*(?:,[0-9]+)?)$");
  591. return r.test(value);
  592. break;
  593. }
  594. return false;
  595. }
  596. //------------------------------------------------
  597. //---------- MULTI-PAGE --------------------------
  598. //------------------------------------------------
  599. function gformDeleteUploadedFile(formId, fieldId, deleteButton){
  600. var parent = jQuery("#field_" + formId + "_" + fieldId);
  601. var fileIndex = jQuery(deleteButton).parent().index();
  602. parent.find(".ginput_preview").eq(fileIndex).remove();
  603. //displaying single file upload field
  604. parent.find("input[type=\"file\"]").removeClass("gform_hidden");
  605. //displaying post image label
  606. parent.find(".ginput_post_image_file").show();
  607. //clearing post image meta fields
  608. parent.find("input[type=\"text\"]").val('');
  609. //removing file from uploaded meta
  610. var files = jQuery.secureEvalJSON(jQuery('#gform_uploaded_files_' + formId).val());
  611. if(files){
  612. var inputName = "input_" + fieldId;
  613. var $multfile = parent.find("#gform_multifile_upload_" + formId + "_" + fieldId );
  614. if( $multfile.length > 0 ) {
  615. files[inputName].splice(fileIndex, 1);
  616. var settings = $multfile.data('settings');
  617. var max = settings.gf_vars.max_files;
  618. jQuery("#" + settings.gf_vars.message_id).html('');
  619. if(files[inputName].length < max)
  620. gfMultiFileUploader.toggleDisabled(settings, false);
  621. } else {
  622. files[inputName] = null;
  623. }
  624. jQuery('#gform_uploaded_files_' + formId).val(jQuery.toJSON(files));
  625. }
  626. }
  627. //------------------------------------------------
  628. //---------- PRICE -------------------------------
  629. //------------------------------------------------
  630. var _gformPriceFields = new Array();
  631. var _anyProductSelected;
  632. function gformIsHidden(element){
  633. return element.parents('.gfield').not(".gfield_hidden_product").css("display") == "none";
  634. }
  635. function gformCalculateTotalPrice(formId){
  636. if(!_gformPriceFields[formId])
  637. return;
  638. var price = 0;
  639. _anyProductSelected = false; //Will be used by gformCalculateProductPrice().
  640. for(var i=0; i<_gformPriceFields[formId].length; i++){
  641. price += gformCalculateProductPrice(formId, _gformPriceFields[formId][i]);
  642. }
  643. //add shipping price if a product has been selected
  644. if(_anyProductSelected){
  645. //shipping price
  646. var shipping = gformGetShippingPrice(formId)
  647. price += shipping;
  648. }
  649. //gform_product_total filter. Allows uers to perform custom price calculation
  650. if(window["gform_product_total"])
  651. price = window["gform_product_total"](formId, price);
  652. price = gform.applyFilters('gform_product_total', price, formId);
  653. //updating total
  654. var totalElement = jQuery(".ginput_total_" + formId);
  655. if(totalElement.length > 0){
  656. totalElement.next().val(price);
  657. totalElement.html(gformFormatMoney(price));
  658. }
  659. }
  660. function gformGetShippingPrice(formId){
  661. var shippingField = jQuery(".gfield_shipping_" + formId + " input[type=\"hidden\"], .gfield_shipping_" + formId + " select, .gfield_shipping_" + formId + " input:checked");
  662. var shipping = 0;
  663. if(shippingField.length == 1 && !gformIsHidden(shippingField)){
  664. if(shippingField.attr("type") && shippingField.attr("type").toLowerCase() == "hidden")
  665. shipping = shippingField.val();
  666. else
  667. shipping = gformGetPrice(shippingField.val());
  668. }
  669. return gformToNumber(shipping);
  670. }
  671. function gformGetFieldId(element){
  672. var id = jQuery(element).attr("id");
  673. var pieces = id.split("_");
  674. if(pieces.length <=0)
  675. return 0;
  676. var fieldId = pieces[pieces.length-1];
  677. return fieldId;
  678. }
  679. function gformCalculateProductPrice(form_id, productFieldId){
  680. var price = gformGetBasePrice(form_id, productFieldId);
  681. var suffix = "_" + form_id + "_" + productFieldId;
  682. //Drop down auto-calculating labels
  683. jQuery(".gfield_option" + suffix + ", .gfield_shipping_" + form_id).find("select").each(function(){
  684. var dropdown_field = jQuery(this);
  685. var selected_price = gformGetPrice(dropdown_field.val());
  686. var field_id = dropdown_field.attr("id").split("_")[2];
  687. dropdown_field.children("option").each(function(){
  688. var choice_element = jQuery(this);
  689. var label = gformGetOptionLabel(choice_element, choice_element.val(), selected_price, form_id, field_id);
  690. choice_element.html(label);
  691. });
  692. });
  693. //Checkboxes labels with prices
  694. jQuery(".gfield_option" + suffix).find(".gfield_checkbox").find("input").each(function(){
  695. var checkbox_item = jQuery(this);
  696. var id = checkbox_item.attr("id");
  697. var field_id = id.split("_")[2];
  698. var label_id = id.replace("choice_", "#label_");
  699. var label_element = jQuery(label_id);
  700. var label = gformGetOptionLabel(label_element, checkbox_item.val(), 0, form_id, field_id);
  701. label_element.html(label);
  702. });
  703. //Radio button auto-calculating lables
  704. jQuery(".gfield_option" + suffix + ", .gfield_shipping_" + form_id).find(".gfield_radio").each(function(){
  705. var selected_price = 0;
  706. var radio_field = jQuery(this);
  707. var id = radio_field.attr("id");
  708. var fieldId = id.split("_")[2];
  709. var selected_value = radio_field.find("input:checked").val();
  710. if(selected_value)
  711. selected_price = gformGetPrice(selected_value);
  712. jQuery(this).find("input").each(function(){
  713. var radio_item = jQuery(this);
  714. var label_id = radio_item.attr("id").replace("choice_", "#label_");
  715. var label_element = jQuery(label_id);
  716. var label = gformGetOptionLabel(label_element, radio_item.val(), selected_price, form_id, fieldId);
  717. label_element.html(label);
  718. });
  719. });
  720. jQuery(".gfield_option" + suffix).find("input:checked, select").each(function(){
  721. if(!gformIsHidden(jQuery(this)))
  722. price += gformGetPrice(jQuery(this).val());
  723. });
  724. var quantity = gformGetProductQuantity( form_id, productFieldId );
  725. //setting global variable if quantity is more than 0 (a product was selected). Will be used when calculating total
  726. if(quantity > 0)
  727. _anyProductSelected = true;
  728. price = price * quantity;
  729. price = Math.round(price * 100) / 100;
  730. return price;
  731. }
  732. function gformGetProductQuantity( formId, productFieldId ) {
  733. var quantity,
  734. quantityInput = jQuery( '#ginput_quantity_' + formId + '_' + productFieldId);
  735. if( quantityInput.length > 0 ) {
  736. quantity = ! gformIsNumber( quantityInput.val() ) ? 0 : quantityInput.val();
  737. } else {
  738. quantityElement = jQuery( '.gfield_quantity_' + formId + '_' + productFieldId);
  739. quantity = 1;
  740. if( quantityElement.find( 'select' ).length > 0 ) {
  741. quantity = quantityElement.find( 'select' ).val();
  742. } else if( quantityElement.find( 'input' ).length > 0 ) {
  743. quantity = quantityElement.find( 'input' ).val();
  744. }
  745. if( ! gformIsNumber( quantity ) )
  746. quantity = 0;
  747. }
  748. quantity = parseFloat( quantity );
  749. return quantity;
  750. }
  751. function gformGetBasePrice(formId, productFieldId){
  752. var suffix = "_" + formId + "_" + productFieldId;
  753. var price = 0;
  754. var productField = jQuery("#ginput_base_price" + suffix+ ", .gfield_donation" + suffix + " input[type=\"text\"], .gfield_product" + suffix + " .ginput_amount");
  755. if(productField.length > 0){
  756. price = productField.val();
  757. //If field is hidden by conditional logic, don't count it for the total
  758. if(gformIsHidden(productField)){
  759. price = 0;
  760. }
  761. }
  762. else
  763. {
  764. productField = jQuery(".gfield_product" + suffix + " select, .gfield_product" + suffix + " input:checked, .gfield_donation" + suffix + " select, .gfield_donation" + suffix + " input:checked");
  765. var val = productField.val();
  766. if(val){
  767. val = val.split("|");
  768. price = val.length > 1 ? val[1] : 0;
  769. }
  770. //If field is hidden by conditional logic, don't count it for the total
  771. if(gformIsHidden(productField))
  772. price = 0;
  773. }
  774. var c = new Currency(gf_global.gf_currency_config);
  775. price = c.toNumber(price);
  776. return price === false ? 0 : price;
  777. }
  778. function gformFormatMoney(text){
  779. if(!gf_global.gf_currency_config)
  780. return text;
  781. var currency = new Currency(gf_global.gf_currency_config);
  782. return currency.toMoney(text);
  783. }
  784. function gformFormatPricingField(element){
  785. if(gf_global.gf_currency_config){
  786. var currency = new Currency(gf_global.gf_currency_config);
  787. var price = currency.toMoney(jQuery(element).val());
  788. jQuery(element).val(price);
  789. }
  790. }
  791. function gformToNumber(text){
  792. var currency = new Currency(gf_global.gf_currency_config);
  793. return currency.toNumber(text);
  794. }
  795. function gformGetPriceDifference(currentPrice, newPrice){
  796. //getting price difference
  797. var diff = parseFloat(newPrice) - parseFloat(currentPrice);
  798. price = gformFormatMoney(diff);
  799. if(diff > 0)
  800. price = "+" + price;
  801. return price;
  802. }
  803. function gformGetOptionLabel(element, selected_value, current_price, form_id, field_id){
  804. element = jQuery(element);
  805. var price = gformGetPrice(selected_value);
  806. var current_diff = element.attr('price');
  807. var original_label = element.html().replace(/<span(.*)<\/span>/i, "").replace(current_diff, "");
  808. var diff = gformGetPriceDifference(current_price, price);
  809. diff = gformToNumber(diff) == 0 ? "" : " " + diff;
  810. element.attr('price', diff);
  811. //don't add <span> for drop down items (not supported)
  812. var price_label = element[0].tagName.toLowerCase() == "option" ? " " + diff : "<span class='ginput_price'>" + diff + "</span>";
  813. var label = original_label + price_label;
  814. //calling hook to allow for custom option formatting
  815. if(window["gform_format_option_label"])
  816. label = gform_format_option_label(label, original_label, price_label, current_price, price, form_id, field_id);
  817. return label;
  818. }
  819. function gformGetProductIds(parent_class, element){
  820. var classes = jQuery(element).hasClass(parent_class) ? jQuery(element).attr("class").split(" ") : jQuery(element).parents("." + parent_class).attr("class").split(" ");
  821. for(var i=0; i<classes.length; i++){
  822. if(classes[i].substr(0, parent_class.length) == parent_class && classes[i] != parent_class)
  823. return {formId: classes[i].split("_")[2], productFieldId: classes[i].split("_")[3]};
  824. }
  825. return {formId:0, fieldId:0};
  826. }
  827. function gformGetPrice(text){
  828. var val = text.split("|");
  829. var currency = new Currency(gf_global.gf_currency_config);
  830. if(val.length > 1 && currency.toNumber(val[1]) !== false)
  831. return currency.toNumber(val[1]);
  832. return 0;
  833. }
  834. function gformRegisterPriceField(item){
  835. if(!_gformPriceFields[item.formId])
  836. _gformPriceFields[item.formId] = new Array();
  837. //ignore price fields that have already been registered
  838. for(var i=0; i<_gformPriceFields[item.formId].length; i++)
  839. if(_gformPriceFields[item.formId][i] == item.productFieldId)
  840. return;
  841. //registering new price field
  842. _gformPriceFields[item.formId].push(item.productFieldId);
  843. }
  844. function gformInitPriceFields(){
  845. jQuery(".gfield_price").each(function(){
  846. var productIds = gformGetProductIds("gfield_price", this);
  847. gformRegisterPriceField(productIds);
  848. jQuery(this).find("input[type=\"text\"], input[type=\"number\"], select").change(function(){
  849. var productIds = gformGetProductIds("gfield_price", this);
  850. if(productIds.formId == 0)
  851. productIds = gformGetProductIds("gfield_shipping", this);
  852. jQuery(document).trigger('gform_price_change', [productIds, this]);
  853. gformCalculateTotalPrice(productIds.formId);
  854. });
  855. jQuery(this).find("input[type=\"radio\"], input[type=\"checkbox\"]").click(function(){
  856. var productIds = gformGetProductIds("gfield_price", this);
  857. if(productIds.formId == 0)
  858. productIds = gformGetProductIds("gfield_shipping", this);
  859. jQuery(document).trigger('gform_price_change', [productIds, this]);
  860. gformCalculateTotalPrice(productIds.formId);
  861. });
  862. });
  863. for(formId in _gformPriceFields){
  864. //needed when implementing for in loops
  865. if(!_gformPriceFields.hasOwnProperty(formId))
  866. continue;
  867. gformCalculateTotalPrice(formId);
  868. }
  869. }
  870. //-------------------------------------------
  871. //---------- PASSWORD -----------------------
  872. //-------------------------------------------
  873. function gformShowPasswordStrength(fieldId){
  874. var password = jQuery("#" + fieldId).val();
  875. var confirm = jQuery("#" + fieldId + "_2").val();
  876. var result = gformPasswordStrength(password, confirm);
  877. var text = window['gf_text']["password_" + result];
  878. jQuery("#" + fieldId + "_strength").val(result);
  879. jQuery("#" + fieldId + "_strength_indicator").removeClass("blank mismatch short good bad strong").addClass(result).html(text);
  880. }
  881. // Password strength meter
  882. function gformPasswordStrength(password1, password2) {
  883. var shortPass = 1, badPass = 2, goodPass = 3, strongPass = 4, mismatch = 5, symbolSize = 0, natLog, score;
  884. if(password1.length <=0)
  885. return "blank";
  886. // password 1 != password 2
  887. if ( (password1 != password2) && password2.length > 0)
  888. return "mismatch";
  889. //password < 4
  890. if ( password1.length < 4 )
  891. return "short";
  892. if ( password1.match(/[0-9]/) )
  893. symbolSize +=10;
  894. if ( password1.match(/[a-z]/) )
  895. symbolSize +=26;
  896. if ( password1.match(/[A-Z]/) )
  897. symbolSize +=26;
  898. if ( password1.match(/[^a-zA-Z0-9]/) )
  899. symbolSize +=31;
  900. natLog = Math.log( Math.pow(symbolSize, password1.length) );
  901. score = natLog / Math.LN2;
  902. if (score < 40 )
  903. return "bad";
  904. if (score < 56 )
  905. return "good";
  906. return "strong";
  907. }
  908. //----------------------------
  909. //------ LIST FIELD ----------
  910. //----------------------------
  911. var gfield_original_title = "";
  912. function gformAddListItem(element, max){
  913. if(jQuery(element).hasClass("gfield_icon_disabled"))
  914. return;
  915. var tr = jQuery(element).closest('tr');
  916. var clone = tr.clone();
  917. clone.find("input, select").val("").attr("tabindex", clone.find('input:last').attr("tabindex"));
  918. tr.after(clone);
  919. gformToggleIcons(tr.parent(), max);
  920. gformAdjustClasses(tr.parent());
  921. }
  922. function gformDeleteListItem(element, max){
  923. var tr = jQuery(element).parent().parent();
  924. var parent = tr.parent();
  925. tr.remove();
  926. gformToggleIcons(parent, max);
  927. gformAdjustClasses(parent);
  928. }
  929. function gformAdjustClasses(table){
  930. var rows = table.children();
  931. for(var i=0; i<rows.length; i++){
  932. var odd_even_class = (i+1) % 2 == 0 ? "gfield_list_row_even" : "gfield_list_row_odd";
  933. jQuery(rows[i]).removeClass("gfield_list_row_odd").removeClass("gfield_list_row_even").addClass(odd_even_class);
  934. }
  935. }
  936. function gformToggleIcons(table, max){
  937. var rowCount = table.children().length;
  938. if(rowCount == 1){
  939. table.find(".delete_list_item").css("visibility", "hidden");
  940. }
  941. else{
  942. table.find(".delete_list_item").css("visibility", "visible");
  943. }
  944. if(max > 0 && rowCount >= max){
  945. gfield_original_title = table.find(".add_list_item:first").attr("title");
  946. table.find(".add_list_item").addClass("gfield_icon_disabled").attr("title", "");
  947. }
  948. else{
  949. var addIcons = table.find(".add_list_item");
  950. addIcons.removeClass("gfield_icon_disabled");
  951. if(gfield_original_title)
  952. addIcons.attr("title", gfield_original_title);
  953. }
  954. }
  955. //-----------------------------------
  956. //------ CREDIT CARD FIELD ----------
  957. //-----------------------------------
  958. function gformMatchCard(id) {
  959. var cardType = gformFindCardType(jQuery('#' + id).val());
  960. var cardContainer = jQuery('#' + id).parents('.gfield').find('.gform_card_icon_container');
  961. if(!cardType) {
  962. jQuery(cardContainer).find('.gform_card_icon').removeClass('gform_card_icon_selected gform_card_icon_inactive');
  963. } else {
  964. jQuery(cardContainer).find('.gform_card_icon').removeClass('gform_card_icon_selected').addClass('gform_card_icon_inactive');
  965. jQuery(cardContainer).find('.gform_card_icon_' + cardType).removeClass('gform_card_icon_inactive').addClass('gform_card_icon_selected');
  966. }
  967. }
  968. function gformFindCardType(value) {
  969. if(value.length < 4)
  970. return false;
  971. var rules = window['gf_cc_rules'];
  972. var validCardTypes = new Array();
  973. for(type in rules) {
  974. //needed when implementing for in loops
  975. if(!rules.hasOwnProperty(type))
  976. continue;
  977. for(i in rules[type]) {
  978. if(!rules[type].hasOwnProperty(i))
  979. continue;
  980. if(rules[type][i].indexOf(value.substring(0, rules[type][i].length)) === 0) {
  981. validCardTypes[validCardTypes.length] = type;
  982. break;
  983. }
  984. }
  985. }
  986. return validCardTypes.length == 1 ? validCardTypes[0].toLowerCase() : false;
  987. }
  988. function gformToggleCreditCard(){
  989. if(jQuery("#gform_payment_method_creditcard").is(":checked"))
  990. jQuery(".gform_card_fields_container").slideDown();
  991. else
  992. jQuery(".gform_card_fields_container").slideUp();
  993. }
  994. //----------------------------------------
  995. //------ CHOSEN DROP DOWN FIELD ----------
  996. //----------------------------------------
  997. function gformInitChosenFields(fieldList, noResultsText){
  998. return jQuery(fieldList).each(function(){
  999. var element = jQuery(this);
  1000. //only initialize once
  1001. if( element.is(":visible") && element.siblings(".chosen-container").length == 0 ){
  1002. var options = gform.applyFilters( 'gform_chosen_options', { no_results_text: noResultsText }, element );
  1003. element.chosen( options );
  1004. }
  1005. });
  1006. }
  1007. //----------------------------------------
  1008. //--- CURRENCY FORMAT NUMBER FIELD -------
  1009. //----------------------------------------
  1010. function gformInitCurrencyFormatFields(fieldList){
  1011. jQuery(fieldList).each(function(){
  1012. var $this = jQuery(this);
  1013. $this.val( gformFormatMoney( jQuery(this).val() ) );
  1014. }).change( function( event ) {
  1015. jQuery(this).val( gformFormatMoney( jQuery(this).val() ) );
  1016. });
  1017. }
  1018. //----------------------------------------
  1019. //------ CALCULATION FUNCTIONS -----------
  1020. //----------------------------------------
  1021. var GFCalc = function(formId, formulaFields){
  1022. this.patt = /{[^{]*?:(\d+(\.\d+)?)(:(.*?))?}/i;
  1023. this.exprPatt = /^[0-9 -/*\(\)]+$/i;
  1024. this.isCalculating = {};
  1025. this.init = function(formId, formulaFields) {
  1026. var calc = this;
  1027. jQuery(document).bind("gform_post_conditional_logic", function(){
  1028. for(var i=0; i<formulaFields.length; i++) {
  1029. var formulaField = jQuery.extend({}, formulaFields[i]);
  1030. calc.runCalc(formulaField, formId);
  1031. }
  1032. });
  1033. for(var i=0; i<formulaFields.length; i++) {
  1034. var formulaField = jQuery.extend({}, formulaFields[i]);
  1035. this.runCalc(formulaField, formId);
  1036. this.bindCalcEvents(formulaField, formId);
  1037. }
  1038. }
  1039. this.runCalc = function(formulaField, formId) {
  1040. var calcObj = this,
  1041. field = jQuery('#field_' + formId + '_' + formulaField.field_id),
  1042. formulaInput = jQuery('#input_' + formId + '_' + formulaField.field_id),
  1043. previous_val = formulaInput.val(),
  1044. formula = gform.applyFilters( 'gform_calculation_formula', formulaField.formula, formulaField, formId, calcObj ),
  1045. expr = calcObj.replaceFieldTags( formId, formula, formulaField ).replace(/(\r\n|\n|\r)/gm,""),
  1046. result = '';
  1047. if(calcObj.exprPatt.test(expr)) {
  1048. try {
  1049. //run calculation
  1050. result = eval(expr);
  1051. } catch( e ) { }
  1052. }
  1053. // if result is postive infinity, negative infinity or a NaN, defaults to 0
  1054. if( ! isFinite( result ) )
  1055. result = 0;
  1056. // allow users to modify result with their own function
  1057. if( window["gform_calculation_result"] ) {
  1058. result = window["gform_calculation_result"](result, formulaField, formId, calcObj);
  1059. if( window.console )
  1060. console.log( '"gform_calculation_result" function is deprecated since version 1.8! Use "gform_calculation_result" JS hook instead.' );
  1061. }
  1062. // allow users to modify result with their own function
  1063. result = gform.applyFilters( 'gform_calculation_result', result, formulaField, formId, calcObj );
  1064. // allow result to be custom formatted
  1065. var formattedResult = gform.applyFilters( 'gform_calculation_format_result', false, result, formulaField, formId, calcObj );
  1066. var numberFormat = gf_global.number_formats[formId][formulaField.field_id];
  1067. //formatting number
  1068. if( formattedResult !== false) {
  1069. result = formattedResult;
  1070. }
  1071. else if( field.hasClass( 'gfield_price' ) || numberFormat == "currency") {
  1072. result = gformFormatMoney(result ? result : 0);
  1073. }
  1074. else {
  1075. var decimalSeparator = ".";
  1076. var thousandSeparator = ",";
  1077. if(numberFormat == "decimal_comma"){
  1078. decimalSeparator = ",";
  1079. thousandSeparator = ".";
  1080. }
  1081. result = gformFormatNumber(result, !gformIsNumber(formulaField.rounding) ? -1 : formulaField.rounding, decimalSeparator, thousandSeparator);
  1082. }
  1083. //If value doesn't change, abort.
  1084. //This is needed to prevent an infinite loop condition with conditional logic
  1085. if( result == previous_val )
  1086. return;
  1087. // if this is a calculation product, handle differently
  1088. if(field.hasClass('gfield_price')) {
  1089. formulaInput.text(result);
  1090. jQuery('#ginput_base_price_' + formId + '_' + formulaField.field_id).val(result).trigger('change');
  1091. gformCalculateTotalPrice(formId);
  1092. } else {
  1093. formulaInput.val(result).trigger('change');
  1094. }
  1095. }
  1096. this.bindCalcEvents = function(formulaField, formId) {
  1097. var calcObj = this;
  1098. var formulaFieldId = formulaField.field_id;
  1099. var matches = getMatchGroups(formulaField.formula, this.patt);
  1100. calcObj.isCalculating[formulaFieldId] = false;
  1101. for(var i in matches) {
  1102. if(! matches.hasOwnProperty(i))
  1103. continue;
  1104. var inputId = matches[i][1];
  1105. var fieldId = parseInt(inputId);
  1106. var input = jQuery('#field_' + formId + '_' + fieldId).find('input[name="input_' + inputId + '"], select[name="input_' + inputId + '"]');
  1107. if(input.prop('type') == 'checkbox' || input.prop('type') == 'radio') {
  1108. jQuery(input).click(function(){
  1109. calcObj.bindCalcEvent(inputId, formulaField, formId, 0);
  1110. });
  1111. } else
  1112. if(input.is('select') || input.prop('type') == 'hidden') {
  1113. jQuery(input).change(function(){
  1114. calcObj.bindCalcEvent(inputId, formulaField, formId, 0);
  1115. });
  1116. } else {
  1117. jQuery(input).keydown(function(){
  1118. calcObj.bindCalcEvent(inputId, formulaField, formId);
  1119. }).change(function(){
  1120. calcObj.bindCalcEvent(inputId, formulaField, formId, 0);
  1121. });
  1122. }
  1123. }
  1124. }
  1125. this.bindCalcEvent = function(inputId, formulaField, formId, delay) {
  1126. var calcObj = this;
  1127. var formulaFieldId = formulaField.field_id;
  1128. delay = delay == undefined ? 345 : delay;
  1129. if(calcObj.isCalculating[formulaFieldId][inputId])
  1130. clearTimeout(calcObj.isCalculating[formulaFieldId][inputId]);
  1131. calcObj.isCalculating[formulaFieldId][inputId] = window.setTimeout(function() {
  1132. calcObj.runCalc(formulaField, formId);
  1133. }, delay);
  1134. }
  1135. this.replaceFieldTags = function( formId, expr, formulaField ) {
  1136. var matches = getMatchGroups(expr, this.patt);
  1137. var origExpr = expr;
  1138. for(i in matches) {
  1139. if(! matches.hasOwnProperty(i))
  1140. continue;
  1141. var inputId = matches[i][1];
  1142. var fieldId = parseInt(inputId);
  1143. var columnId = matches[i][3];
  1144. var value = 0;
  1145. var input = jQuery('#field_' + formId + '_' + fieldId).find('input[name="input_' + inputId + '"], select[name="input_' + inputId + '"]');
  1146. // radio buttons will return multiple inputs, checkboxes will only return one but it may not be selected, filter out unselected inputs
  1147. if( input.length > 1 || input.prop('type') == 'checkbox' )
  1148. input = input.filter(':checked');
  1149. var isVisible = window['gf_check_field_rule'] ? gf_check_field_rule( formId, fieldId, true, '' ) == 'show' : true;
  1150. if( input.length > 0 && isVisible ) {
  1151. var val = input.val();
  1152. val = val.split( '|' );
  1153. if( val.length > 1 ) {
  1154. value = val[1];
  1155. } else {
  1156. value = input.val();
  1157. }
  1158. }
  1159. var numberFormat = gf_global.number_formats[formId][fieldId];
  1160. if( ! numberFormat )
  1161. numberFormat = gf_global.number_formats[formId][formulaField.field_id];
  1162. var decimalSeparator = gformGetDecimalSeparator(numberFormat);
  1163. value = gformCleanNumber( value, '', '', decimalSeparator );
  1164. if( ! value )
  1165. value = 0;
  1166. expr = expr.replace( matches[i][0], value );
  1167. }
  1168. return expr;
  1169. }
  1170. this.init(formId, formulaFields);
  1171. }
  1172. function gformFormatNumber(number, rounding, decimalSeparator, thousandSeparator){
  1173. if(typeof decimalSeparator == "undefined"){
  1174. if(window['gf_global']){
  1175. var currency = new Currency(gf_global.gf_currency_config);
  1176. decimalSeparator = currency.currency["decimal_separator"];
  1177. }
  1178. else{
  1179. decimalSeparator = ".";
  1180. }
  1181. }
  1182. if(typeof thousandSeparator == "undefined"){
  1183. if(window['gf_global']){
  1184. var currency = new Currency(gf_global.gf_currency_config);
  1185. thousandSeparator = currency.currency["thousand_separator"];
  1186. }
  1187. else{
  1188. thousandSeparator = ",";
  1189. }
  1190. }
  1191. var currency = new Currency();
  1192. return currency.numberFormat(number, rounding, decimalSeparator, thousandSeparator, false)
  1193. }
  1194. function gformToNumber(text) {
  1195. var currency = new Currency(gf_global.gf_currency_config);
  1196. return currency.toNumber(text);
  1197. }
  1198. function getMatchGroups(expr, patt) {
  1199. var matches = new Array();
  1200. while(patt.test(expr)) {
  1201. var i = matches.length;
  1202. matches[i] = patt.exec(expr)
  1203. expr = expr.replace('' + matches[i][0], '');
  1204. }
  1205. return matches;
  1206. }
  1207. //----------------------------------------
  1208. //------ JAVASCRIPT HOOK FUNCTIONS -------
  1209. //----------------------------------------
  1210. var gform = {
  1211. hooks: { action: {}, filter: {} },
  1212. addAction: function( action, callable, priority, tag ) {
  1213. gform.addHook( 'action', action, callable, priority, tag );
  1214. },
  1215. addFilter: function( action, callable, priority, tag ) {
  1216. gform.addHook( 'filter', action, callable, priority, tag );
  1217. },
  1218. doAction: function( action ) {
  1219. gform.doHook( 'action', action, arguments );
  1220. },
  1221. applyFilters: function( action ) {
  1222. return gform.doHook( 'filter', action, arguments );
  1223. },
  1224. removeAction: function( action, tag ) {
  1225. gform.removeHook( 'action', action, tag );
  1226. },
  1227. removeFilter: function( action, priority, tag ) {
  1228. gform.removeHook( 'filter', action, priority, tag );
  1229. },
  1230. addHook: function( hookType, action, callable, priority, tag ) {
  1231. if ( undefined == gform.hooks[hookType][action] ) {
  1232. gform.hooks[hookType][action] = [];
  1233. }
  1234. var hooks = gform.hooks[hookType][action];
  1235. if ( undefined == tag ) {
  1236. tag = action + '_' + hooks.length;
  1237. }
  1238. gform.hooks[hookType][action].push( { tag:tag, callable:callable, priority:priority } );
  1239. },
  1240. doHook: function( hookType, action, args ) {
  1241. // splice args from object into array and remove first index which is the hook name
  1242. args = Array.prototype.slice.call(args, 1);
  1243. if ( undefined != gform.hooks[hookType][action] ) {
  1244. var hooks = gform.hooks[hookType][action], hook;
  1245. //sort by priority
  1246. hooks.sort(function(a,b){return a["priority"]-b["priority"]});
  1247. for( var i=0; i<hooks.length; i++) {
  1248. hook = hooks[i].callable;
  1249. if(typeof hook != 'function')
  1250. hook = window[hook];
  1251. if ( 'action' == hookType ) {
  1252. hook.apply(null, args);
  1253. } else {
  1254. args[0] = hook.apply(null, args);
  1255. }
  1256. }
  1257. }
  1258. if ( 'filter'==hookType ) {
  1259. return args[0];
  1260. }
  1261. },
  1262. removeHook: function( hookType, action, priority, tag ) {
  1263. if ( undefined != gform.hooks[hookType][action] ) {
  1264. var hooks = gform.hooks[hookType][action];
  1265. for( var i=hooks.length-1; i>=0; i--) {
  1266. if ((undefined==tag||tag==hooks[i].tag) && (undefined==priority||priority==hooks[i].priority)){
  1267. hooks.splice(i,1);
  1268. }
  1269. }
  1270. }
  1271. }
  1272. };
  1273. //----------------------------------------
  1274. //------ MULTIFILE UPLOAD FUNCTIONS ------
  1275. //----------------------------------------
  1276. (function (gfMultiFileUploader, $) {
  1277. gfMultiFileUploader.uploaders = {};
  1278. var strings = typeof gform_gravityforms != 'undefined' ? gform_gravityforms.strings : {};
  1279. var imagesUrl = typeof gform_gravityforms != 'undefined' ? gform_gravityforms.vars.images_url : "";
  1280. $(document).ready(function () {
  1281. if((typeof adminpage !== 'undefined' && adminpage === 'toplevel_page_gf_edit_forms')|| typeof plupload == 'undefined'){
  1282. $(".gform_button_select_files").prop("disabled", true);
  1283. } else if (typeof adminpage !== 'undefined'){
  1284. $(".gform_fileupload_multifile").each(function(){
  1285. setup(this);
  1286. });
  1287. } else {
  1288. $(document).bind('gform_post_render', function(e, formID){
  1289. $("form#gform_" + formID + " .gform_fileupload_multifile").each(function(){
  1290. setup(this);
  1291. });
  1292. var $form = $("form#gform_" + formID);
  1293. if($form.length > 0){
  1294. $form.submit(function(){
  1295. var pendingUploads = false;
  1296. $.each(gfMultiFileUploader.uploaders, function(i, uploader){
  1297. if(uploader.total.queued>0){
  1298. pendingUploads = true;
  1299. return false;
  1300. }
  1301. });
  1302. if(pendingUploads){
  1303. alert(strings.currently_uploading);
  1304. window["gf_submitting_" + formID] = false;
  1305. return false;
  1306. }
  1307. });
  1308. }
  1309. });
  1310. $(document).bind("gform_post_conditional_logic", function(e,formID, fields, isInit){
  1311. if(!isInit){
  1312. $.each(gfMultiFileUploader.uploaders, function(i, uploader){
  1313. uploader.refresh();
  1314. });
  1315. }
  1316. });
  1317. }
  1318. });
  1319. function setup(uploadElement){
  1320. var settings = $(uploadElement).data('settings');
  1321. var uploader = new plupload.Uploader(settings);
  1322. formID = uploader.settings.multipart_params.form_id;
  1323. gfMultiFileUploader.uploaders[settings.container] = uploader;
  1324. var formID;
  1325. var uniqueID;
  1326. uploader.bind('Init', function(up, params) {
  1327. if(!up.features.dragdrop)
  1328. $(".gform_drop_instructions").hide();
  1329. var fieldID = up.settings.multipart_params.field_id;
  1330. var maxFiles = parseInt(up.settings.gf_vars.max_files);
  1331. var initFileCount = countFiles(fieldID);
  1332. if(maxFiles > 0 && initFileCount >= maxFiles){
  1333. gfMultiFileUploader.toggleDisabled(up.settings, true);
  1334. }
  1335. });
  1336. gfMultiFileUploader.toggleDisabled = function (settings, disabled){
  1337. var button = typeof settings.browse_button == "string" ? $("#" + settings.browse_button) : $(settings.browse_button);
  1338. button.prop("disabled", disabled);
  1339. }
  1340. function addMessage(messagesID, message){
  1341. $("#" + messagesID).prepend("<li>" + message + "</li>");
  1342. }
  1343. uploader.init();
  1344. uploader.bind('FilesAdded', function(up, files) {
  1345. var max = parseInt(up.settings.gf_vars.max_files),
  1346. fieldID = up.settings.multipart_params.field_id,
  1347. totalCount = countFiles(fieldID),
  1348. disallowed = up.settings.gf_vars.disallowed_extensions,
  1349. extension;
  1350. if( max > 0 && totalCount >= max){
  1351. $.each(files, function(i, file) {
  1352. up.removeFile(file);
  1353. return;
  1354. })
  1355. return;
  1356. }
  1357. $.each(files, function(i, file) {
  1358. extension = file.name.split('.').pop();
  1359. if($.inArray(extension, disallowed) > -1){
  1360. addMessage(up.settings.gf_vars.message_id, file.name + " - " + strings.illegal_extension);
  1361. up.removeFile(file);
  1362. return;
  1363. }
  1364. if ((file.status == plupload.FAILED) || (max > 0 && totalCount >= max)){
  1365. up.removeFile(file);
  1366. return;
  1367. }
  1368. var size = typeof file.size !== 'undefined' ? plupload.formatSize(file.size) : strings.in_progress;
  1369. var status = '<div id="'
  1370. + file.id
  1371. + '" class="ginput_preview">'
  1372. + file.name
  1373. + ' (' + size + ') <b></b> '
  1374. + '<a href="javascript:void(0)" title="' + strings.cancel_upload + '" onclick=\'$this=jQuery(this); var uploader = gfMultiFileUploader.uploaders.' + up.settings.container + ';uploader.stop();uploader.removeFile(uploader.getFile("' + file.id +'"));$this.after("' + strings.cancelled + '"); uploader.start();$this.remove();\'>' + strings.cancel + '</a>'
  1375. + '</div>';
  1376. $('#' + up.settings.filelist).prepend(status);
  1377. totalCount++;
  1378. });
  1379. up.refresh(); // Reposition Flash
  1380. var formElementID = "form#gform_" + formID;
  1381. var uidElementID = "input:hidden[name='gform_unique_id']";
  1382. var uidSelector = formElementID + " " + uidElementID;
  1383. var $uid = $(uidSelector);
  1384. if($uid.length==0){
  1385. $uid = $(uidElementID);
  1386. }
  1387. uniqueID = $uid.val();
  1388. if('' === uniqueID){
  1389. uniqueID = generateUniqueID();
  1390. $uid.val(uniqueID);
  1391. }
  1392. if(max > 0 && totalCount >= max){
  1393. addMessage(up.settings.gf_vars.message_id, strings.max_reached)
  1394. gfMultiFileUploader.toggleDisabled(up.settings, true);
  1395. }
  1396. up.settings.multipart_params.gform_unique_id = uniqueID;
  1397. up.start();
  1398. });
  1399. uploader.bind('UploadProgress', function(up, file) {
  1400. var html = file.percent + "%";
  1401. $('#' + file.id + " b").html(html);
  1402. });
  1403. uploader.bind('Error', function(up, err) {
  1404. if(err.code === plupload.FILE_EXTENSION_ERROR){
  1405. var extensions = typeof up.settings.filters.mime_types != 'undefined' ? up.settings.filters.mime_types[0].extensions /* plupoad 2 */ : up.settings.filters[0].extensions;
  1406. addMessage(up.settings.gf_vars.message_id, err.file.name + " - " + strings.invalid_file_extension + " " + extensions);
  1407. } else if (err.code === plupload.FILE_SIZE_ERROR) {
  1408. addMessage(up.settings.gf_vars.message_id, err.file.name + " - " + strings.file_exceeds_limit);
  1409. } else {
  1410. var m = "<li>Error: " + err.code +
  1411. ", Message: " + err.message +
  1412. (err.file ? ", File: " + err.file.name : "") +
  1413. "</li>";
  1414. addMessage(up.settings.gf_vars.message_id, m);
  1415. }
  1416. $('#' + err.file.id ).html('');
  1417. up.refresh(); // Reposition Flash
  1418. });
  1419. uploader.bind('FileUploaded', function(up, file, result) {
  1420. var response = $.secureEvalJSON(result.response);
  1421. if(response.status == "error"){
  1422. addMessage(up.settings.gf_vars.message_id, file.name + " - " + response.error.message);
  1423. $('#' + file.id ).html('');
  1424. return;
  1425. }
  1426. var html = '<strong>' + file.name + '</strong>';
  1427. var formId = up.settings.multipart_params.form_id;
  1428. var fieldId = up.settings.multipart_params.field_id;
  1429. html = "<img "
  1430. + "class='gform_delete' "
  1431. + "src='" + imagesUrl + "/delete.png' "
  1432. + "onclick='gformDeleteUploadedFile(" + formId + "," + fieldId + ", this);' "
  1433. + "alt='"+ strings.delete_file + "' "
  1434. + "title='" + strings.delete_file
  1435. + "' /> "
  1436. + html;
  1437. $('#' + file.id ).html(html);
  1438. var fieldID = up.settings.multipart_params["field_id"];
  1439. if(file.percent == 100){
  1440. if(response.status && response.status == 'ok'){
  1441. addFile(fieldID, response.data);
  1442. } else {
  1443. addMessage(up.settings.gf_vars.message_id, strings.unknown_error);
  1444. }
  1445. }
  1446. });
  1447. function getAllFiles(){
  1448. var selector = '#gform_uploaded_files_' + formID,
  1449. $uploadedFiles = $(selector), files;
  1450. files = $uploadedFiles.val();
  1451. files = '' === files ? {} : $.parseJSON(files);
  1452. return files;
  1453. }
  1454. function getFiles(fieldID){
  1455. var allFiles = getAllFiles();
  1456. var inputName = getInputName(fieldID);
  1457. if(typeof allFiles[inputName] == 'undefined')
  1458. allFiles[inputName] = [];
  1459. return allFiles[inputName];
  1460. }
  1461. function countFiles(fieldID){
  1462. var files = getFiles(fieldID);
  1463. return files.length;
  1464. }
  1465. function addFile(fieldID, fileInfo){
  1466. var files = getFiles(fieldID);
  1467. files.unshift(fileInfo);
  1468. setUploadedFiles(fieldID, files);
  1469. }
  1470. function setUploadedFiles(fieldID, files){
  1471. var allFiles = getAllFiles();
  1472. var $uploadedFiles = $('#gform_uploaded_files_' + formID);
  1473. var inputName = getInputName(fieldID);
  1474. allFiles[inputName] = files;
  1475. $uploadedFiles.val($.toJSON(allFiles));
  1476. }
  1477. function getInputName(fieldID){
  1478. return "input_" + fieldID;
  1479. }
  1480. // fixes drag and drop in IE10
  1481. $("#" + settings.drop_element).on({
  1482. "dragenter": ignoreDrag,
  1483. "dragover": ignoreDrag
  1484. });
  1485. function ignoreDrag( e ) {
  1486. e.preventDefault();
  1487. }
  1488. }
  1489. function generateUniqueID() {
  1490. return 'xxxxxxxx'.replace(/[xy]/g, function (c) {
  1491. var r = Math.random() * 16 | 0, v = c == 'x' ? r : r & 0x3 | 0x8;
  1492. return v.toString(16);
  1493. });
  1494. }
  1495. }(window.gfMultiFileUploader = window.gfMultiFileUploader || {}, jQuery));
  1496. //----------------------------------------
  1497. //------ GENERAL FUNCTIONS -------
  1498. //----------------------------------------
  1499. function gformInitSpinner( formId, spinnerUrl ) {
  1500. if( typeof spinnerUrl == 'undefined' || ! spinnerUrl )
  1501. spinnerUrl = gform.applyFilters( "gform_spinner_url", gf_global.spinnerUrl, formId );
  1502. jQuery('#gform_' + formId).submit(function () {
  1503. if (jQuery('#gform_ajax_spinner_' + formId).length == 0) {
  1504. jQuery('#gform_submit_button_' + formId + ', #gform_wrapper_' + formId + ' .gform_next_button')
  1505. .after('<img id="gform_ajax_spinner_' + formId + '" class="gform_ajax_spinner" src="' + spinnerUrl + '" alt="" />');
  1506. }
  1507. });
  1508. }
  1509. /*============================================
  1510. Stripe
  1511. ==============================================*/
  1512. (function(){var e,t,n,r,i,s={}.hasOwnProperty,o=function(e,t){function r(){this.constructor=e}for(var n in t)s.call(t,n)&&(e[n]=t[n]);return r.prototype=t.prototype,e.prototype=new r,e.__super__=t.prototype,e},u=this;this.Stripe=function(){function e(){}return e.version=2,e.endpoint="https://api.stripe.com/v1",e.setPublishableKey=function(t){return e.key=t,e.utils.validateProtocol(e.key)},e._corsGateAmount=0,e._corsGate=function(){return Math.random()<this._corsGateAmount},e._transport=typeof window!="undefined"&&window!==null&&e._corsGate()&&"XMLHttpRequest"in window&&"withCredentials"in new XMLHttpRequest?"cors":"jsonp",e.request=function(t){return t.data.payment_user_agent?t.data.payment_user_agent=""+t.data.payment_user_agent+" ("+e.stripejs_ua+")":t.data.payment_user_agent=e.stripejs_ua,this._transport==="cors"?this.xhr(t):this.ajaxJSONP(t)},e.complete=function(t,n){return function(r,i,s){var o;if(r!=="success")return o=Math.round((new Date).getTime()/1e3),(new Image).src="https://q.stripe.com?event=stripejs-error&type="+r+"&key="+e.key+"&timestamp="+o+"&payment_user_agent="+encodeURIComponent(e.stripejs_ua),typeof t=="function"?t(500,{error:{code:r,type:r,message:n}}):void 0}},e}.call(this),e=this.Stripe,this.Stripe.token=function(){function t(){}return t.validate=function(e,t){if(!e)throw t+" required";if(typeof e!="object")throw t+" invalid"},t.formatData=function(t,n){return e.utils.isElement(t)&&(t=e.utils.paramsFromForm(t,n)),e.utils.underscoreKeys(t),t},t.create=function(t,n){return t.key||(t.key=e.key||e.publishableKey),e.utils.validateKey(t.key),e.request({url:""+e.endpoint+"/tokens",data:t,method:"POST",success:function(e,t){return typeof n=="function"?n(t,e):void 0},complete:e.complete(n,"A network error has occurred, and you have not been charged. Please try again."),timeout:4e4})},t.get=function(t,n){if(!t)throw"token required";return e.utils.validateKey(e.key),e.request({url:""+e.endpoint+"/tokens/"+t,data:{key:e.key},success:function(e,t){return typeof n=="function"?n(t,e):void 0},complete:e.complete(n,"A network error has occurred loading data from Stripe. Please try again."),timeout:4e4})},t}.call(this),this.Stripe.card=function(t){function n(){return n.__super__.constructor.apply(this,arguments)}return o(n,t),n.tokenName="card",n.whitelistedAttrs=["number","cvc","exp_month","exp_year","name","address_line1","address_line2","address_city","address_state","address_zip","address_country"],n.createToken=function(t,r,i){var s;return r==null&&(r={}),e.token.validate(t,"card"),typeof r=="function"?(i=r,r={}):typeof r!="object"&&(s=parseInt(r,10),r={},s>0&&(r.amount=s)),r[n.tokenName]=e.token.formatData(t,n.whitelistedAttrs),e.token.create(r,i)},n.getToken=function(t,n){return e.token.get(t,n)},n.validateCardNumber=function(e){return e=(e+"").replace(/\s+|-/g,""),e.length>=10&&e.length<=16&&n.luhnCheck(e)},n.validateCVC=function(t){return t=e.utils.trim(t),/^\d+$/.test(t)&&t.length>=3&&t.length<=4},n.validateExpiry=function(t,n){var r,i;return t=e.utils.trim(t),n=e.utils.trim(n),/^\d+$/.test(t)?/^\d+$/.test(n)?1<=t&&t<=12?(n.length===2&&(n<70?n="20"+n:n="19"+n),n.length!==4?!1:(i=new Date(n,t),r=new Date,i.setMonth(i.getMonth()-1),i.setMonth(i.getMonth()+1,1),i>r)):!1:!1:!1},n.luhnCheck=function(e){var t,n,r,i,s,o;r=!0,i=0,n=(e+"").split("").reverse();for(s=0,o=n.length;s<o;s++){t=n[s],t=parseInt(t,10);if(r=!r)t*=2;t>9&&(t-=9),i+=t}return i%10===0},n.cardType=function(e){return n.cardTypes[e.slice(0,2)]||"Unknown"},n.cardBrand=function(e){return n.cardType(e)},n.cardTypes=function(){var e,t,n,r;t={};for(e=n=40;n<=49;e=++n)t[e]="Visa";for(e=r=50;r<=59;e=++r)t[e]="MasterCard";return t[34]=t[37]="American Express",t[60]=t[62]=t[64]=t[65]="Discover",t[35]="JCB",t[30]=t[36]=t[38]=t[39]="Diners Club",t}(),n}.call(this,this.Stripe.token),this.Stripe.bankAccount=function(t){function n(){return n.__super__.constructor.apply(this,arguments)}return o(n,t),n.tokenName="bank_account",n.whitelistedAttrs=["country","routing_number","account_number"],n.createToken=function(t,r,i){return r==null&&(r={}),e.token.validate(t,"bank account"),typeof r=="function"&&(i=r,r={}),r[n.tokenName]=e.token.formatData(t,n.whitelistedAttrs),e.token.create(r,i)},n.getToken=function(t,n){return e.token.get(t,n)},n.validateRoutingNumber=function(t,r){t=e.utils.trim(t);switch(r){case"US":return/^\d+$/.test(t)&&t.length===9&&n.routingChecksum(t);case"CA":return/\d{5}\-\d{3}/.test(t)&&t.length===9;default:return!0}},n.validateAccountNumber=function(t,n){t=e.utils.trim(t);switch(n){case"US":return/^\d+$/.test(t)&&t.length>=1&&t.length<=17;default:return!0}},n.routingChecksum=function(e){var t,n,r,i,s,o;r=0,t=(e+"").split(""),o=[0,3,6];for(i=0,s=o.length;i<s;i++)n=o[i],r+=parseInt(t[n])*3,r+=parseInt(t[n+1])*7,r+=parseInt(t[n+2]);return r!==0&&r%10===0},n}.call(this,this.Stripe.token),this.Stripe.bitcoinReceiver=function(){function t(){}return t._whitelistedAttrs=["amount","currency","email","description"],t.createReceiver=function(t,n){var r;return e.token.validate(t,"bitcoin_receiver data"),r=e.token.formatData(t,this._whitelistedAttrs),r.key=e.key||e.publishableKey,e.utils.validateKey(r.key),e.request({url:""+e.endpoint+"/bitcoin/receivers",data:r,method:"POST",success:function(e,t){return typeof n=="function"?n(t,e):void 0},complete:e.complete(n,"A network error has occurred while creating a Bitcoin address. Please try again."),timeout:4e4})},t.getReceiver=function(t,n){var r;if(!t)throw"receiver id required";return r=e.key||e.publishableKey,e.utils.validateKey(r),e.request({url:""+e.endpoint+"/bitcoin/receivers/"+t,data:{key:r},success:function(e,t){return typeof n=="function"?n(t,e):void 0},complete:e.complete(n,"A network error has occurred loading data from Stripe. Please try again."),timeout:4e4})},t._activeReceiverPolls={},t._clearReceiverPoll=function(e){return delete t._activeReceiverPolls[e]},t._pollInterval=1500,t.pollReceiver=function(e,t){if(this._activeReceiverPolls[e]!=null)throw"You are already polling receiver "+e+". Please cancel that poll before polling it again.";return this._activeReceiverPolls[e]={},this._pollReceiver(e,t)},t._pollReceiver=function(e,n){t.getReceiver(e,function(r,i){var s,o;if(t._activeReceiverPolls[e]==null)return;return r===200&&i.filled?(t._clearReceiverPoll(e),typeof n=="function"?n(r,i):void 0):r>=400&&r<500?(t._clearReceiverPoll(e),typeof n=="function"?n(r,i):void 0):(s=r===500?5e3:t._pollInterval,o=setTimeout(function(){return t._pollReceiver(e,n)},s),t._activeReceiverPolls[e].timeoutId=o)})},t.cancelReceiverPoll=function(e){var n;n=t._activeReceiverPolls[e];if(n==null)throw"You are not polling receiver "+e+".";n["timeoutId"]!=null&&clearTimeout(n.timeoutId),t._clearReceiverPoll(e)},t}.call(this),t=["createToken","getToken","cardType","validateExpiry","validateCVC","validateCardNumber"];for(r=0,i=t.length;r<i;r++)n=t[r],this.Stripe[n]=this.Stripe.card[n];typeof module!="undefined"&&module!==null&&(module.exports=this.Stripe),typeof define=="function"&&define("stripe",[],function(){return u.Stripe})}).call(this),function(){var e=[].indexOf||function(e){for(var t=0,n=this.length;t<n;t++)if(t in this&&this[t]===e)return t;return-1};this.Stripe.utils=function(){function r(){}var t,n;return n=/(,)|(\[|{)|(}|])|"(?:[^"\\\r\n]|\\["\\\/bfnrt]|\\u[\da-fA-F]{4})*"\s*:?|true|false|null|-?(?!0\d)\d+(?:\.\d+|)(?:[eE][+-]?\d+|)/g,t=/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g,r.trim=function(e){return e===null?"":(e+"").replace(t,"")},r.parseJSON=function(e){var t,r,i,s;if((s=window.JSON)!=null?s.parse:void 0)return window.JSON.parse(e+"");r=void 0,t=null,i=Stripe.utils.trim(e+"");if(i&&!Stripe.utils.trim(i.replace(n,function(e,n,i,s){return r&&n&&(t=0),t===0?e:(r=i||n,t+=!s-!i,"")})))return Function("return "+i)();throw new Error("Invalid JSON: "+e)},r.serialize=function(e,t,n){var r,i;t==null&&(t=[]);for(r in e)i=e[r],n&&(r=""+n+"["+r+"]"),typeof i=="object"?this.serialize(i,t,r):t.push(""+r+"="+encodeURIComponent(i));return t.join("&").replace(/%20/g,"+")},r.underscore=function(e){return(e+"").replace(/([A-Z])/g,function(e){return"_"+e.toLowerCase()}).replace(/-/g,"_")},r.underscoreKeys=function(e){var t,n,r;r=[];for(t in e)n=e[t],delete e[t],r.push(e[this.underscore(t)]=n);return r},r.isElement=function(e){return typeof e!="object"?!1:typeof jQuery!="undefined"&&jQuery!==null&&e instanceof jQuery?!0:e.nodeType===1},r.paramsFromForm=function(t,n){var r,i,s,o,u,a,f,l,c,h;n==null&&(n=[]),typeof jQuery!="undefined"&&jQuery!==null&&t instanceof jQuery&&(t=t[0]),s=t.getElementsByTagName("input"),u=t.getElementsByTagName("select"),a={};for(f=0,c=s.length;f<c;f++){i=s[f],r=this.underscore(i.getAttribute("data-stripe"));if(e.call(n,r)<0)continue;a[r]=i.value}for(l=0,h=u.length;l<h;l++){o=u[l],r=this.underscore(o.getAttribute("data-stripe"));if(e.call(n,r)<0)continue;o.selectedIndex!=null&&(a[r]=o.options[o.selectedIndex].value)}return a},r.validateProtocol=function(e){var t;if(!e||typeof e!="string")return;if(/_live_/g.test(e)&&window.location.protocol!=="https:"&&((t=window.console)!=null?t.warn:void 0)!=null)return window.console.warn("You are using Stripe.js in live mode over an insecure connection. This is considered unsafe. Please conduct live requests only on sites served over https. For more info, see https://stripe.com/help/ssl")},r.validateKey=function(e){if(!e||typeof e!="string")throw new Error("You did not set a valid publishable key. Call Stripe.setPublishableKey() with your publishable key. For more info, see https://stripe.com/docs/stripe.js");if(/\s/g.test(e))throw new Error("Your key is invalid, as it contains whitespace. For more info, see https://stripe.com/docs/stripe.js");if(/^sk_/.test(e))throw new Error("You are using a secret key with Stripe.js, instead of the publishable one. For more info, see https://stripe.com/docs/stripe.js")},r}()}.call(this),function(){var e,t=[].slice;e=(new Date).getTime(),this.Stripe.ajaxJSONP=function(n){var r,i,s,o,u,a;return n==null&&(n={}),s="sjsonp"+ ++e,u=document.createElement("script"),i=null,r=function(e){var t;return e==null&&(e="abort"),clearTimeout(i),(t=u.parentNode)!=null&&t.removeChild(u),s in window&&(window[s]=function(){}),typeof n.complete=="function"?n.complete(e,a,n):void 0},a={abort:r},u.onerror=function(){return a.abort(),typeof n.error=="function"?n.error(a,n):void 0},window[s]=function(){var e;e=1<=arguments.length?t.call(arguments,0):[],clearTimeout(i),u.parentNode.removeChild(u);try{delete window[s]}catch(r){window[s]=void 0}return typeof n.success=="function"&&n.success.apply(n,e),typeof n.complete=="function"?n.complete("success",a,n):void 0},n.data||(n.data={}),n.data.callback=s,n.method&&(n.data._method=n.method),u.src=n.url+"?"+Stripe.utils.serialize(n.data),o=document.getElementsByTagName("head")[0],o.appendChild(u),n.timeout>0&&(i=setTimeout(function(){return a.abort("timeout")},n.timeout)),a}}.call(this),function(){var e,t,n,r,i,s,o,u,a,f={}.hasOwnProperty;t={contentType:"application/x-www-form-urlencoded",accept:{json:"application/json"}},o=/^(20\d|1223)$/,s="invalid_json_response",r=function(e,t,n){return function(){if(e._aborted)return n("aborted");if(e.request&&e.request.readyState===4)return e.request.onreadystatechange=function(){},o.test(e.request.status)?t(e.request,e.request.status):(t(e.request,e.request.status),n("response_code"))}},u=function(e,n){var r,i,s;i=n.headers||{},i.Accept||(i.Accept=t.accept.json),i["Content-Type"]||(i["Content-Type"]=t.contentType),s=[];for(r in i){if(!f.call(i,r))continue;"setRequestHeader"in e?s.push(e.setRequestHeader(r,i[r])):s.push(void 0)}return s},a=function(e,t){return/\?/.test(e)?e+"&"+t:e+"?"+t},n=function(e,t){var n,i,s,o,f,l,c,h;return f=this.o,o=(f.method||"GET").toUpperCase(),l=f.url,s=(c=f.data)!=null?c.key:void 0,n=Stripe.utils.serialize(f.data),i=void 0,o==="GET"&&n&&(l=a(l,n),n=null),h=new XMLHttpRequest,h.open(o,l,!0),u(h,f),h.onreadystatechange=r(this,e,t),h.send(n),h},e=function(e){return this.o=e,i.apply(this,arguments)},i=function(e){var t,r,i,o=this;return this.url=e.url,this.timeout=null,this._successHandler=function(){},this._errorHandlers=[],this._completeHandlers=[],e.timeout&&(this.timeout=setTimeout(function(){return o.abort()},e.timeout)),e.success&&(this._successHandler=function(){return e.success.apply(e,arguments)}),e.error&&this._errorHandlers.push(function(){return e.error.apply(e,arguments)}),e.complete&&this._completeHandlers.push(function(){return e.complete.apply(e,arguments)}),t=function(t){var n;e.timeout&&clearTimeout(o.timeout),o.timeout=null,n=[];while(o._completeHandlers.length>0)n.push(o._completeHandlers.shift()("success",t,e));return n},i=function(e,n){var i;i=e.responseText;if(i)try{e=Stripe.utils.parseJSON(i)}catch(u){r(s)}return o._successHandler(e,n),t(e)},r=function(e){var n,r;r=o.request,n=r.responseText;if(n)try{r=Stripe.utils.parseJSON(n)}catch(i){e=s}while(o._errorHandlers.length>0)o._errorHandlers.shift()(r,e);return t(r)},this.request=n.call(this,i,r)},e.prototype={abort:function(){return this._aborted=!0,this.request.abort()}},this.Stripe.xhr=function(t){return new e(t)}}.call(this),function(){var e=[].indexOf||function(e){for(var t=0,n=this.length;t<n;t++)if(t in this&&this[t]===e)return t;return-1};this.Stripe.validator={"boolean":function(e,t){if(t!=="true"&&t!=="false")return"Enter a boolean string (true or false)"},integer:function(e,t){if(!/^\d+$/.test(t))return"Enter an integer"},positive:function(e,t){if(!(!this.integer(e,t)&&parseInt(t,10)>0))return"Enter a positive value"},range:function(t,n){var r;if(r=parseInt(n,10),e.call(t,r)<0)return"Needs to be between "+t[0]+" and "+t[t.length-1]},required:function(e,t){if(e&&(t==null||t===""))return"Required"},year:function(e,t){if(!/^\d{4}$/.test(t))return"Enter a 4-digit year"},birthYear:function(e,t){var n;n=this.year(e,t);if(n)return n;if(parseInt(t,10)>2e3)return"You must be over 18";if(parseInt(t,10)<1900)return"Enter your birth year"},month:function(e,t){if(this.integer(e,t))return"Please enter a month";if(this.range([1,2,3,4,5,6,7,8,9,10,11,12],t))return"Needs to be between 1 and 12"},choices:function(t,n){if(e.call(t,n)<0)return"Not an acceptable value for this field"},email:function(e,t){if(!/^[^@<\s>]+@[^@<\s>]+$/.test(t))return"That doesn't look like an email address"},url:function(e,t){if(!/^https?:\/\/.+\..+/.test(t))return"Not a valid url"},usTaxID:function(e,t){if(!/^\d{2}-?\d{1}-?\d{2}-?\d{4}$/.test(t))return"Not a valid tax ID"},ein:function(e,t){if(!/^\d{2}-?\d{7}$/.test(t))return"Not a valid EIN"},ssnLast4:function(e,t){if(!/^\d{4}$/.test(t))return"Not a valid last 4 digits for an SSN"},ownerPersonalID:function(e,t){var n;n=function(){switch(e){case"CA":return/^\d{3}-?\d{3}-?\d{3}$/.test(t);case"US":return!0}}();if(!n)return"Not a valid ID"},bizTaxID:function(e,t){var n,r,i,s,o,u,a,f;u={CA:["Tax ID",[/^\d{9}$/]],US:["EIN",[/^\d{2}-?\d{7}$/]]},o=u[e];if(o!=null){n=o[0],s=o[1],r=!1;for(a=0,f=s.length;a<f;a++){i=s[a];if(i.test(t)){r=!0;break}}if(!r)return"Not a valid "+n}},zip:function(e,t){var n;n=function(){switch(e.toUpperCase()){case"CA":return/^[\d\w]{6}$/.test(t!=null?t.replace(/\s+/g,""):void 0);case"US":return/^\d{5}$/.test(t)||/^\d{9}$/.test(t)}}();if(!n)return"Not a valid zip"},bankAccountNumber:function(e,t){if(!/^\d{1,17}$/.test(t))return"Invalid bank account number"},usRoutingNumber:function(e){var t,n,r,i,s,o,u;if(!/^\d{9}$/.test(e))return"Routing number must have 9 digits";s=0;for(t=o=0,u=e.length-1;o<=u;t=o+=3)n=parseInt(e.charAt(t),10)*3,r=parseInt(e.charAt(t+1),10)*7,i=parseInt(e.charAt(t+2),10),s+=n+r+i;if(s===0||s%10!==0)return"Invalid routing number"},caRoutingNumber:function(e){if(!/^\d{5}\-\d{3}$/.test(e))return"Invalid transit number"},routingNumber:function(e,t){switch(e.toUpperCase()){case"CA":return this.caRoutingNumber(t);case"US":return this.usRoutingNumber(t)}},phoneNumber:function(e,t){var n;n=t.replace(/[^0-9]/g,"");if(n.length!==10)return"Invalid phone number"},bizDBA:function(e,t){if(!/^.{1,23}$/.test(t))return"Statement descriptors can only have up to 23 characters"},nameLength:function(e,t){if(t.length===1)return"Names need to be longer than one character"}}}.call(this),function(){this.Stripe.stripejs_ua="stripe.js/d24d225"}.call(this);
  1513. /*============================================
  1514. Stripe - Front-end
  1515. ==============================================*/
  1516. window.GFStripe = null;
  1517. (function($){
  1518. GFStripe = function( args ) {
  1519. for( var prop in args ) {
  1520. if( args.hasOwnProperty( prop ) )
  1521. this[prop] = args[prop];
  1522. }
  1523. this.form = null;
  1524. this.init = function() {
  1525. if( ! this.isCreditCardOnPage() )
  1526. return;
  1527. var GFStripeObj = this;
  1528. Stripe.setPublishableKey( this.apiKey );
  1529. // initialize spinner
  1530. if( ! this.isAjax )
  1531. gformInitSpinner( this.formId );
  1532. // bind Stripe functionality to submit event
  1533. $( '#gform_' + this.formId ).submit( function( event ){
  1534. event.preventDefault();
  1535. var form = $(this),
  1536. ccInputPrefix = 'input_' + GFStripeObj.formId + '_' + GFStripeObj.ccFieldId + '_',
  1537. cc = {
  1538. number: form.find( '#' + ccInputPrefix + '1' ).val(),
  1539. exp_month: form.find( '#' + ccInputPrefix + '2_month' ).val(),
  1540. exp_year: form.find( '#' + ccInputPrefix + '2_year' ).val(),
  1541. cvc: form.find( '#' + ccInputPrefix + '3' ).val(),
  1542. name: form.find( '#' + ccInputPrefix + '5').val()
  1543. };
  1544. GFStripeObj.form = form;
  1545. Stripe.card.createToken( cc, function( status, response ) {
  1546. GFStripeObj.responseHandler( status, response );
  1547. } );
  1548. } );
  1549. };
  1550. this.responseHandler = function( status, response ) {
  1551. var form = this.form,
  1552. ccInputPrefix = 'input_' + this.formId + '_' + this.ccFieldId + '_',
  1553. ccInputSuffixes = [ '1', '2_month', '2_year', '3', '5' ],
  1554. cardType = false;
  1555. // remove "name" attribute from credit card inputs
  1556. for( var i = 0; i < ccInputSuffixes.length; i++ ) {
  1557. var input = form.find( '#' + ccInputPrefix + ccInputSuffixes[i] );
  1558. if( ccInputSuffixes[i] == '1' ) {
  1559. var ccNumber = $.trim( input.val() ),
  1560. cardType = gformFindCardType( ccNumber );
  1561. if( typeof this.cardLabels[cardType] != 'undefined' )
  1562. cardType = this.cardLabels[cardType];
  1563. form.append( $( '<input type="hidden" name="stripe_credit_card_last_four" />' ).val( ccNumber.slice( -4 ) ) );
  1564. form.append( $( '<input type="hidden" name="stripe_credit_card_type" />' ).val( cardType ) );
  1565. }
  1566. input.attr( 'name', null );
  1567. }
  1568. // append stripe.js response
  1569. form.append( $( '<input type="hidden" name="stripe_response" />' ).val( $.toJSON( response ) ) );
  1570. // submit the form
  1571. form.get(0).submit();
  1572. }
  1573. this.isLastPage = function() {
  1574. var targetPageInput = $( '#gform_target_page_number_' + this.formId );
  1575. if( targetPageInput.length > 0 )
  1576. return targetPageInput.val() == 0;
  1577. return true;
  1578. }
  1579. this.isCreditCardOnPage = function() {
  1580. var currentPage = this.getCurrentPageNumber();
  1581. // if current page is false or no credit card page number, assume this is not a multi-page form
  1582. if( ! this.ccPage || ! currentPage )
  1583. return true;
  1584. return this.ccPage == currentPage;
  1585. }
  1586. this.getCurrentPageNumber = function() {
  1587. var currentPageInput = $( '#gform_source_page_number_' + this.formId );
  1588. return currentPageInput.length > 0 ? currentPageInput.val() : false;
  1589. }
  1590. this.init();
  1591. }
  1592. })(jQuery);