PageSourceSearch

https://treyhunner.com/javascripts/funnel-tools-capture.js

js treyhunner.com collected 2026-09-25 14:06:00 UTC 6,815 bytes, 197 lines download raw bytes

1/*!
2 * Funnel Tools Capture Library v1.1.0
3 * http://brandonhilkert.com/funnel-tools/capture
4 *
5 * Copyright 2015 Big Blue Media, LLC
6 * http://brandonhilkert.com
7 *
8 * Date: 2015-02-20T13:58Z
9 */
10
11window.FunnelTools || (window.FunnelTools = {});
12FunnelTools.Capture = {
13    showTime: 32000,
14
15    init: function(opts) {
16        if (opts && opts.showTime) {
17            this.showTime = opts.showTime;
18        }
19        try {
20            this.expiredStorage = new ExpiredStorage();
21        } catch (exc) {
22            console.error(exc);
23        }
24
25        // The collapsed/open states are pure CSS (see funnel-tools-capture.css),
26        // so nothing is measured or positioned here.
27        this.triggerShow(this.showTime);
28    },
29    widget: function() {
30        return $("#funnel-tools-capture");
31    },
32    open: function() {
33        return $("#funnel-tools-capture .open");
34    },
35
36    close: function() {
37        return $("#funnel-tools-capture .close");
38    },
39    show: function() {
40        this.widget().addClass('open');
41        if (this.expiredStorage) {
42            this.expiredStorage.setItem('toasterShown', true, 3600 * 24 * 5); // 5 days
43        }
44    },
45    triggerShow: function(time) {
46        var that = this;
47
48        setTimeout(function() {
49            if (!that.wasShown()) {
50                that.show();
51            }
52        }, time);
53    },
54    wasShown: function() {
55        return this.expiredStorage && this.expiredStorage.getItem('toasterShown');
56    },
57    hide: function() {
58        this.widget().removeClass('open');
59    },
60    toggle: function() {
61        if (!this.isVisible()) {
62            this.show();
63        } else {
64            this.hide();
65        }
66    },
67    isVisible: function() {
68        return this.widget().hasClass('open');
69    },
70}
71
72$(document).on("click", "#funnel-tools-capture .title, #funnel-tools-capture .open, #funnel-tools-capture .close", function() {
73    FunnelTools.Capture.toggle();
74});
75
76// Hide widget when clicking outside
77$(document).click(function(event) {
78    if (!FunnelTools.Capture.isVisible()) {
79        return;
80    }
81    if ($(event.target).parents("#funnel-tools-capture").length === 0) {
82        FunnelTools.Capture.hide();
83    }
84});
85
86function gaSend(obj) {
87    if (typeof ga !== "undefined") {
88        try {
89            ga('send', obj);
90        } catch (e) {
91            console.error(e);
92        }
93    } else {
94        console.error('Google Analytics not loaded on page.');
95    }
96}
97
98$(document).ready(function() {
99    FunnelTools.Capture.init();
100
101    function submitHandler($form) {
102        var $submit = $form.find('*[type=submit]');
103        var $title = $("#funnel-tools-capture .title");
104        var $description = $("#funnel-tools-capture .description");
105        var $email = $("#funnel-tools-capture input[type=email]");
106        $submit
107            .prop('disabled', true)
108            .data('submitText', $submit.text())
109            .text('Submitting...');
110        gaSend({
111            hitType: 'event',
112            eventCategory: 'Python Morsels',
113            eventAction: 'button click',
114            eventLabel: 'Toaster Widget'
115        });
116        $.ajax({
117            url: $form.attr('action'),
118            method: 'POST',
119            data: $form.serialize()
120        }).always(function() {
121            $submit
122                .prop('disabled', false)
123                .text($submit.data('submitText'));
124        }).done(function(data, textStatus, xhr) {
125            if (xhr.status == 201) {
126                var thanksMessage = $('#morsels-signup-thanks').html();
127                $title.html('You just signed up!... almost');
128                $description.html(thanksMessage);
129                if ($email.val().indexOf("gmail.com") != -1) {
130                    $description.find('.email-message').html('<p><a href="https://mail.google.com" target="_blank">Go to Gmail to continue</a> :)</p>')
131                }
132                gaSend({
133                    hitType: 'event',
134                    eventCategory: 'Python Morsels',
135                    eventAction: 'signup',
136                    eventLabel: 'Toaster Widget'
137                });
138            } else if (data.code == 1) {
139                $description.html("You've already signed up with that email.  You can <a href=\"https://www.pythonmorsels.com/accounts/login/\">login here</a>.")
140                gaSend({
141                    hitType: 'event',
142                    eventCategory: 'Python Morsels',
143                    eventAction: 'email already signed up',
144                    eventLabel: 'Toaster Widget'
145                });
146            } else if (data.code == 3) {
147                $email.next('span.error').remove();
148                $email.after('<span class="error">Email invalid</span>');
149                $email.addClass('error');
150                gaSend({
151                    hitType: 'event',
152                    eventCategory: 'Python Morsels',
153                    eventAction: 'email invalid',
154                    eventLabel: 'Toaster Widget'
155                });
156            } else {
157                alert("An unexpected error occurred while submitting this form.  Sorry!  Please feel free to contact Trey to troubleshoot.");
158                console.error(data, textStatus, xhr);
159                gaSend({
160                    hitType: 'event',
161                    eventCategory: 'Python Morsels',
162                    eventAction: 'server error',
163                    eventLabel: 'Toaster Widget'
164                });
165            }
166        }).fail(function(xhr, textStatus, error) {
167            if (xhr.status == 401) {
168                $description.html("You've already signed up with that email.  You can <a href=\"https://www.pythonmorsels.com/accounts/login/\">login here</a>.")
169            } else if (xhr.status == 400) {
170                $email.next('span.error').remove();
171                $email.after('<span class="error">Email invalid</span>');
172                $email.addClass('error');
173            } else {
174                alert("An unexpected error occurred while submitting this form.  Sorry!  Please feel free to contact Trey to troubleshoot.");
175            }
176        });
177    }
178
179    $("#funnel-tools-capture form[action*=pythonmorsels]").submit(function(event) {
180        var $form = $(event.target);
181        grecaptcha.ready(function() {
182            grecaptcha.execute('6LfP0cEUAAAAAAlbI-d5M7xLioNYWX0LDj78gN2b', {
183                action: 'signup'
184            }).then(function(token) {
185                $form.find('*[name=captcha_token]').val(token);
186                submitHandler($form);
187            });
188        });
189        event.preventDefault();
190    });
191
192    $("#funnel-tools-capture input[type=email]").focus(function(event) {
193        var $email = $(event.target);
194        $email.removeClass('error')
195        $email.next('span.error').remove();
196    });
197});

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.