PageSourceSearch

https://freethinker.co.uk/wp-content/plugins/seamless-donations/js/seamless-donations.js?ver=7.1.2

js freethinker.co.uk collected 2026-10-02 07:35:28 UTC 17,605 bytes, 399 lines download raw bytes

1/*
2 Seamless Donations by David Gewirtz, adopted from Allen Snook
3
4 Lab Notes: http://zatzlabs.com/lab-notes/
5 Plugin Page: http://zatzlabs.com/seamless-donations/
6 Contact: http://zatzlabs.com/contact-us/
7
8 Copyright (c) 2015 by David Gewirtz
9 */
10
11jQuery(document).ready(function () {
12
13    // this is the new option that generates the UUID in the browser
14    // UUID code based on https://github.com/broofa/node-uuid
15
16    jQuery("input[name='_dgx_donate_session_id']").val(function () {
17        var guid = jQuery(this).val();
18        var ver = 'SDB01-'; // Session ID version: SD=Seamless Donations, B=Browser, 01=first versiom
19
20        if (guid === "browser-uuid") {
21            return ver + uuid.v4().toUpperCase();
22        } else {
23            return guid;
24        }
25    });
26
27    // radio button revealer, works with multiple sets per page
28    // each input tag gets either (or both) a data-revealer or data-hide attribute
29    // the contents of that attribute is a class or id (with the . or # as part of the string)
30    // for the purposes of the forms engine, we'll work only with classes.
31
32    jQuery("input:radio").change(function () {
33        var revealTarget = jQuery(this).attr("data-reveal");
34        var concealTarget = jQuery(this).attr("data-conceal");
35        var checkTarget = jQuery(this).attr('data-check');
36        var uncheckTarget = jQuery(this).attr('data-uncheck');
37        if (revealTarget !== undefined) {
38            console.log("radio button: show " + revealTarget);
39            jQuery(revealTarget).show('fast');
40            showSelectedOptions(revealTarget);
41        }
42        if (concealTarget !== undefined) {
43            console.log("radio button: hide " + concealTarget);
44            jQuery(concealTarget).hide('fast');
45            hideSelectedOptions(concealTarget);
46        }
47        if (jQuery(this).is(":checked")) {
48            checkSelectedNamedItems(checkTarget);
49            uncheckSelectedNamedItems(uncheckTarget);
50        }
51    });
52
53    // checkbox revealer, also works with multiple checkbox and hide/reveal sets per page
54    // this uses only the data-revealer attribute, and reveals if checked and hides if unchecked.
55
56    jQuery("input:checkbox").click(function () {
57        var revealTarget = jQuery(this).attr('data-reveal');
58        var concealTarget = jQuery(this).attr('data-conceal');
59        var checkTarget = jQuery(this).attr('data-check');
60        var uncheckTarget = jQuery(this).attr('data-uncheck');
61        if (checkTarget !== undefined) {
62            console.log("checkbox checktarget:" + checkTarget);
63        }
64        if (jQuery(this).is(":checked")) {
65            console.log("checkbox click:is-checked (revealTarget:" + revealTarget + ")");
66            jQuery(revealTarget).show('fast');
67            showSelectedOptions(revealTarget);
68            checkSelectedNamedItems(checkTarget);
69            uncheckSelectedNamedItems(uncheckTarget);
70        }
71        if (jQuery(this).is(":not(:checked)")) {
72            console.log("checkbox click:not-checked");
73            //hideSelect();
74            hideSelectedOptions(concealTarget);
75            jQuery(revealTarget).hide('fast');
76        }
77    });
78
79
80    function checkSelectedNamedItems(whatToCheck) {
81        if (whatToCheck !== undefined) {
82            var whatToCheckArray = whatToCheck.split(" ");
83            for (itemToCheckIndex in whatToCheckArray) {
84                var itemToCheck = whatToCheckArray[itemToCheckIndex];
85                console.log("-- checkSelectedNamedItems (itemToCheck):" + itemToCheck);
86                jQuery("[id=" + itemToCheck + "] input").attr('checked', true);
87            }
88        }
89    }
90
91    function uncheckSelectedNamedItems(whatToCheck) {
92        if (whatToCheck !== undefined) {
93            var whatToCheckArray = whatToCheck.split(" ");
94            for (itemToCheckIndex in whatToCheckArray) {
95                var itemToCheck = whatToCheckArray[itemToCheckIndex];
96                console.log("-- checkSelectedNamedItems (itemToCheck):" + itemToCheck);
97                jQuery("[id=" + itemToCheck + "] input").attr('checked', false);
98            }
99        }
100    }
101
102
103    jQuery("form").on("change", "select", function () {
104        var nameOfChangedSelect = jQuery(this).attr("name");
105        console.log("select change (invoked):" + nameOfChangedSelect);
106        jQuery("select[name=" + nameOfChangedSelect + "] option:selected").each(function () {
107            // triggering for everything, not just visible items
108            var parent = jQuery(this).parent("select").attr("name");
109            console.log("-- option:selected (parent select): " + parent);
110            var reveal = jQuery(this).attr("data-reveal");
111            console.log("---- option:selected (reveal: " + reveal);
112            var optionKey = jQuery(this).attr("value");
113            console.log("---- option:selected (optionKey): " + optionKey);
114            var conceal = jQuery(this).parent("select").attr("data-conceal");
115            console.log("---- option:selected (conceal): " + conceal);
116
117            hideSelectedOptions(conceal);
118            jQuery(reveal).show();
119        });
120    }).on("change");
121
122    // if the select item that matches the cloak becomes visible, make the active option classes visible
123    // we're looking at the class of the select item to see if it matches the what to reveal values
124    function showSelectedOptions(whatToReveal) {
125        // whatToReveal could be a set of classes
126        if (whatToReveal !== undefined) {
127            console.log("showSelectedOptions (" + whatToReveal + ")");
128            var whatToRevealArray = whatToReveal.split(",");
129            for (itemToCheckIndex in whatToRevealArray) {
130                var itemToReveal = whatToRevealArray[itemToCheckIndex];
131                console.log("-- showSelectedOptions (itemToReveal):" + itemToReveal);
132                jQuery("select" + itemToReveal + " option:selected").each(function () {
133                    var reveal = jQuery(this).attr("data-reveal");
134                    jQuery(reveal).show();
135                    var optionKey = jQuery(this).attr("value");
136                    console.log("-- showSelectedOptions (option key:" + optionKey + "):" + reveal);
137                });
138            }
139        }
140    }
141
142    function hideSelectedOptions(whatToConceal) {
143        // whatToConceal could be a set of classes
144        console.log("hideSelectedOptions (" + whatToConceal + ")");
145        if (whatToConceal !== undefined) {
146            var whatToConcealArray = whatToConceal.split(",");
147            for (itemToConcealIndex in whatToConcealArray) {
148                var itemToConceal = whatToConcealArray[itemToConcealIndex].trim();
149                console.log("-- hideSelectedOptions (itemToConceal):" + itemToConceal);
150                jQuery("select" + itemToConceal + " option:selected").each(function () {
151                    var conceal = jQuery(this).attr("data-conceal");
152                    jQuery(conceal).show();
153                    var optionKey = jQuery(this).attr("value");
154                    console.log("-- showSelectedOptions (option key:" + optionKey + "):" + conceal);
155                });
156                jQuery(itemToConceal).hide();
157            }
158        }
159    }
160
161    // should be showSelectedOptions?
162    function showSelectedOptionsx(whatToReveal) {
163        // whatToReveal could be a set of classes
164        var whatToRevealArray = whatToReveal.split(",");
165        console.log("showSelectedOptions (" + whatToReveal + ")");
166        jQuery("select option:selected").each(function () {
167            var reveal = jQuery(this).attr("data-reveal");
168            if (reveal !== undefined) {
169                var revealArray = reveal.split(",");
170
171                for (itemToCheckIndex in whatToRevealArray) {
172                    var itemToReveal = whatToRevealArray[itemToCheckIndex];
173                    console.log("-- showSelectedOptions itemToReveal: " + whatToRevealArray[itemToCheckIndex]);
174                    for (classToRevealIndex in revealArray) {
175                        var classToReveal = revealArray[classToRevealIndex];
176                        console.log("-- showSelectedOptions classToReveal: " + classToReveal);
177                        if (itemToReveal.trim() == classToReveal.trim()) {
178                            console.log("---- showSelectedOptions revealing: " + itemToReveal);
179                            jQuery(itemToReveal).show();
180                        }
181                    }
182                }
183            }
184        });
185    }
186
187
188    // unhacked version -- hacking new one called showSelectedOptions
189    function showSelect() {
190        console.log("showSelect (invoked)");
191        jQuery("select option:selected").each(function () {
192            var reveal = jQuery(this).attr("data-reveal");
193            var optionKey = jQuery(this).attr("value");
194            console.log("-- showSelect (option key:" + optionKey + "):" + reveal);
195            jQuery(reveal).show();
196        });
197    }
198
199    function hideSelect() {
200        jQuery("select option:selected").each(function () {
201            var conceal = jQuery(this).parent("select").attr("data-conceal");
202            console.log("hideSelect:" + conceal);
203            jQuery(conceal).hide();
204        });
205    }
206});
207
208/**
209 * @return {boolean}
210 */
211function SeamlessDonationsFormsEngineValidator() {
212    var formOkay = true;
213
214    // first hide the error message data
215    jQuery('.seamless-donations-forms-error-message').hide('fast').text();
216    jQuery('.seamless-donations-error-message-field').hide('fast');
217
218    // the approach is to find visible elements with 'validation' and check them
219    jQuery('#seamless-donations-form input:visible').each(function (index) {
220        var validations = jQuery(this).attr('data-validate');
221        if (validations !== undefined) {
222            // the element has a validation request
223            // the validation request can be one or more validation names, separated by commas
224            var validationArray = validations.split(",");
225            var valDex;
226            for (valDex = 0; valDex < validationArray.length; ++valDex) {
227                var validationTest = validationArray[valDex];
228                switch (validationTest) {
229                    case 'required':
230                        if (!SeamlessDonationsValidateRequired(this)) {
231                            formOkay = false;
232                        }
233                        break;
234                    case 'currency':
235                        if (!SeamlessDonationsValidateCurrency(this)) {
236                            formOkay = false;
237                        }
238                        break;
239                    case 'email':
240                        if (!SeamlessDonationsValidateEmail(this)) {
241                            formOkay = false;
242                        }
243                        break;
244                }
245            }
246        }
247    });
248
249    console.log("SeamlessDonationsFormsEngineValidator: before if(!formOkay)");
250    if (!formOkay) {
251        jQuery('.seamless-donations-forms-error-message').text('Please correct your input.').show('fast');
252        jQuery('body').scrollTop(0);
253        console.log("-- SeamlessDonationsFormsEngineValidator: form not okay");
254        return false; // returning false blocks the page loader from executing on submit
255    } else {
256        // the form is okay, so go on to the form submit function, another JavaScript
257        console.log("-- SeamlessDonationsFormsEngineValidator: form passed validation");
258        return true;
259    }
260}
261
262function SeamlessDonationsValidateRequired(validationObject) {
263    var elementID = jQuery(validationObject).attr('id');
264    var elementType = jQuery(validationObject).attr('type');
265    var elementName = jQuery(validationObject).attr('name');
266    var elementValue = jQuery(validationObject).val();
267    if (elementType == 'text') {
268        var divSelector = "input[name=" + elementName + "]";
269        var errorSelector = "div[id=" + elementName + "-error-message]";
270        if (SeamlessDonationsTrim(elementValue) == '') {
271            jQuery('#seamless-donations-form').find(divSelector).addClass('seamless-donations-invalid-input');
272            jQuery('#seamless-donations-form').find(errorSelector).text('This is a required field.').show('fast');
273
274            return false;
275        } else {
276            jQuery('#seamless-donations-form').find(divSelector).removeClass('seamless-donations-invalid-input');
277            return true
278        }
279
280    }
281    if (elementType == 'radio' || elementType == 'checkbox') {
282        valid = jQuery(validationObject).prop("checked");
283    }
284
285    if (valid) {
286        jQuery('#seamless-donations-form').find(divSelector).removeClass('seamless-donations-invalid-input');
287        return true;
288    } else {
289        jQuery('#seamless-donations-form').find(divSelector).addClass('seamless-donations-invalid-input');
290        jQuery('#seamless-donations-form').find(errorSelector).text('This is a required field.').show('fast');
291        return false;
292    }
293    return true;
294}
295
296function SeamlessDonationsValidateEmail(validationObject) {
297
298    var elementID = jQuery(validationObject).attr('id');
299    var elementType = jQuery(validationObject).attr('type');
300    var elementName = jQuery(validationObject).attr('name');
301    var elementValue = jQuery(validationObject).val();
302
303    if (elementType == 'text' && elementValue != '') {
304        var divSelector = "input[name=" + elementName + "]";
305        var errorSelector = "div[id=" + elementName + "-error-message]";
306
307        var lastAtPos = elementValue.lastIndexOf('@');
308        var lastDotPos = elementValue.lastIndexOf('.');
309        var isEmail = (lastAtPos < lastDotPos && lastAtPos > 0
310            && elementValue.indexOf('@@') == -1 && lastDotPos > 2 && (elementValue.length - lastDotPos) > 2);
311        if (!isEmail) {
312            jQuery('#seamless-donations-form').find(divSelector).addClass('seamless-donations-invalid-input');
313            jQuery('#seamless-donations-form').find(errorSelector).text('Please enter a valid email address.').show('fast');
314            return false;
315        }
316        jQuery('#seamless-donations-form').find(divSelector).removeClass('seamless-donations-invalid-input');
317    }
318    return true;
319}
320
321function SeamlessDonationsValidateCurrency(validationObject) {
322    var elementID = jQuery(validationObject).attr('id');
323    var elementType = jQuery(validationObject).attr('type');
324    var elementName = jQuery(validationObject).attr('name');
325    var elementValue = jQuery(validationObject).val();
326
327    if (elementType == 'text') {
328
329        var divSelector = "input[name=" + elementName + "]";
330        var errorSelector = "div[id=" + elementName + "-error-message]";
331
332        // Check if amount is empty
333        if (!elementValue) {
334            jQuery('#seamless-donations-form').find(divSelector).addClass('seamless-donations-invalid-input');
335            jQuery('#seamless-donations-form').find(errorSelector).text('This is a required field.').show('fast');
336            return false;
337        }
338
339        // Check for anything other than numbers and decimal points
340        var matchTest = elementValue.match(/[^0123456789.]/g);
341        if (matchTest != null) {
342            jQuery('#seamless-donations-form').find(divSelector).addClass('seamless-donations-invalid-input');
343            jQuery('#seamless-donations-form').find(errorSelector).text('Please use only numbers.').show('fast');
344            return false;
345        }
346
347        // Count the number of decimal points
348        var pointCount = DgxDonateCountNeedles(".", elementValue);
349
350        // If more than one decimal point, fail right away
351        if (pointCount > 1) {
352            jQuery('#seamless-donations-form').find(divSelector).addClass('seamless-donations-invalid-input');
353            jQuery('#seamless-donations-form').find(errorSelector).text('Please use only numbers.').show('fast');
354            return false;
355        }
356
357        // A leading zero is not allowed
358        if (elementValue.substr(0, 1) == "0") {
359            jQuery('#seamless-donations-form').find(divSelector).addClass('seamless-donations-invalid-input');
360            jQuery('#seamless-donations-form').find(errorSelector).text('A leading zero is not allowed.').show('fast');
361            return false;
362        }
363
364        // A leading decimal point is not allowed (minimum donation is 1.00)
365        if (elementValue.substr(0, 1) == ".") {
366            jQuery('#seamless-donations-form').find(divSelector).addClass('seamless-donations-invalid-input');
367            jQuery('#seamless-donations-form').find(errorSelector).text('Minimum value is 1.00.').show('fast');
368            return false;
369        }
370
371        // If we have a decimal point and there is anything other than two digits after it, fail
372        if (pointCount == 1) {
373            var pointIndex = elementValue.indexOf(".");
374            if (pointIndex + 2 != (elementValue.length - 1)) {
375                jQuery('#seamless-donations-form').find(divSelector).addClass('seamless-donations-invalid-input');
376                jQuery('#seamless-donations-form').find(errorSelector).text('Please use only numbers.').show('fast');
377                return false;
378            }
379        }
380        jQuery('#seamless-donations-form').find(divSelector).removeClass('seamless-donations-invalid-input');
381    }
382    return true;
383}
384
385function SeamlessDonationsTrim(s) {
386    if (s == undefined) {
387        s = "";
388    }
389
390    s = s.replace(/(^\s*)|(\s*$)/gi, "");
391    s = s.replace(/[ ]{2,}/gi, " ");
392    s = s.replace(/\n /, "\n");
393    return s;
394}
395
396function DgxDonateCountNeedles(a, b) {
397    var c = b.split(a) - 1;
398    return c.length;
399}

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.