form.js 71 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063
  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 - Front-end
  1511. ==============================================*/
  1512. window.GFStripe = null;
  1513. (function($){
  1514. GFStripe = function( args ) {
  1515. for( var prop in args ) {
  1516. if( args.hasOwnProperty( prop ) )
  1517. this[prop] = args[prop];
  1518. }
  1519. this.form = null;
  1520. this.init = function() {
  1521. if( ! this.isCreditCardOnPage() )
  1522. return;
  1523. var GFStripeObj = this;
  1524. Stripe.setPublishableKey( this.apiKey );
  1525. // initialize spinner
  1526. if( ! this.isAjax )
  1527. gformInitSpinner( this.formId );
  1528. // bind Stripe functionality to submit event
  1529. $( '#gform_' + this.formId ).submit( function( event ){
  1530. event.preventDefault();
  1531. var form = $(this),
  1532. ccInputPrefix = 'input_' + GFStripeObj.formId + '_' + GFStripeObj.ccFieldId + '_',
  1533. cc = {
  1534. number: form.find( '#' + ccInputPrefix + '1' ).val(),
  1535. exp_month: form.find( '#' + ccInputPrefix + '2_month' ).val(),
  1536. exp_year: form.find( '#' + ccInputPrefix + '2_year' ).val(),
  1537. cvc: form.find( '#' + ccInputPrefix + '3' ).val(),
  1538. name: form.find( '#' + ccInputPrefix + '5').val()
  1539. };
  1540. GFStripeObj.form = form;
  1541. Stripe.card.createToken( cc, function( status, response ) {
  1542. GFStripeObj.responseHandler( status, response );
  1543. } );
  1544. } );
  1545. };
  1546. this.responseHandler = function( status, response ) {
  1547. var form = this.form,
  1548. ccInputPrefix = 'input_' + this.formId + '_' + this.ccFieldId + '_',
  1549. ccInputSuffixes = [ '1', '2_month', '2_year', '3', '5' ],
  1550. cardType = false;
  1551. // remove "name" attribute from credit card inputs
  1552. for( var i = 0; i < ccInputSuffixes.length; i++ ) {
  1553. var input = form.find( '#' + ccInputPrefix + ccInputSuffixes[i] );
  1554. if( ccInputSuffixes[i] == '1' ) {
  1555. var ccNumber = $.trim( input.val() ),
  1556. cardType = gformFindCardType( ccNumber );
  1557. if( typeof this.cardLabels[cardType] != 'undefined' )
  1558. cardType = this.cardLabels[cardType];
  1559. form.append( $( '<input type="hidden" name="stripe_credit_card_last_four" />' ).val( ccNumber.slice( -4 ) ) );
  1560. form.append( $( '<input type="hidden" name="stripe_credit_card_type" />' ).val( cardType ) );
  1561. }
  1562. input.attr( 'name', null );
  1563. }
  1564. // append stripe.js response
  1565. form.append( $( '<input type="hidden" name="stripe_response" />' ).val( $.toJSON( response ) ) );
  1566. // submit the form
  1567. form.get(0).submit();
  1568. }
  1569. this.isLastPage = function() {
  1570. var targetPageInput = $( '#gform_target_page_number_' + this.formId );
  1571. if( targetPageInput.length > 0 )
  1572. return targetPageInput.val() == 0;
  1573. return true;
  1574. }
  1575. this.isCreditCardOnPage = function() {
  1576. var currentPage = this.getCurrentPageNumber();
  1577. // if current page is false or no credit card page number, assume this is not a multi-page form
  1578. if( ! this.ccPage || ! currentPage )
  1579. return true;
  1580. return this.ccPage == currentPage;
  1581. }
  1582. this.getCurrentPageNumber = function() {
  1583. var currentPageInput = $( '#gform_source_page_number_' + this.formId );
  1584. return currentPageInput.length > 0 ? currentPageInput.val() : false;
  1585. }
  1586. this.init();
  1587. }
  1588. })(jQuery);