PageSourceSearch

https://www.fundable.com/web/v1/js/fundable/common.js?_cache=1790238290

js fundable.com collected 2026-09-24 08:25:28 UTC 19,822 bytes, 632 lines download raw bytes

1if(!Fundable) {
2	var Fundable = {};
3}
4$(document).ready(function() { Fundable.init(); });
5
6Fundable.init = function() {
7    if(Fundable.UI)
8    {
9        Fundable.UI.init();
10    }
11
12    Fundable.Common.initFollowButtons();
13
14
15};
16
17Fundable.Common = {
18    nl2br:function(str) {
19          var breakTag = '<br/>'; // Adjust comment to avoid issue on phpjs.org display
20
21          return (str + '').replace(/([^>\r\n]?)(\r\n|\n\r|\r|\n)/g, '$1' + breakTag + '$2');
22
23    },
24    setCookie:function(name, value, days)
25    {
26        var exdate = new Date();
27        var exdays = days;
28        var c_name = name;
29        var c_value = value;
30        exdate.setDate(exdate.getDate() + exdays);
31        var c_value = escape(c_value) + ((exdays == null) ? "" : "; expires=" + exdate.toUTCString());
32        document.cookie = c_name + "=" + c_value;
33    },
34    parseJson:function(thing) {
35        if (typeof thing == 'object') {
36            return thing;
37        } else {
38            var response = {success:false};
39            try
40            {
41                response = $.parseJSON(thing);
42            }
43            catch(err)
44            {
45                console.log(err);
46            }
47            return response;
48        }
49    },
50    initTabs:function() {
51        Fundable.UI.Tabs.init();
52    },
53    initFollowButtons:function() {
54
55        $('.btn.follow').hover(function(){
56            if($(this).hasClass('success'))
57            {
58                $(this).toggleClass('success danger');
59            }
60        }, function() { 
61            if( $(this).hasClass('danger') )
62            { 
63                $(this).toggleClass('success danger');
64            }
65        });
66        $('.btn.follow').on('click', function(e) {
67            e.preventDefault();
68            var url = $(this).attr('data-url');
69            var followButtonId = $(this).attr('data-follow-id');
70            var $followButtons = $('*[data-follow-id="'+followButtonId+'"]');
71            var $followCounts = $('*[data-count-follow-id="'+followButtonId+'"]');
72
73            $followButtons.addClass('loading');
74            $followButtons.removeClass('success danger');
75
76            Fundable.Common.ajaxRequest('POST', url, {}, function(response) {
77                response = Fundable.Common.parseJson(response);
78                if(response.success)
79                {
80                    var action = response.action; /* this will be '+' for follows, '-' for unfollows */
81                    var count = parseInt(response.count);
82                    $followCounts.html(count);
83                    $followButtons.removeClass('loading');
84                    if(action == '+')
85                    {
86                        $followButtons.addClass('success');
87                    }
88                }
89                else if(!response.auth)
90                {
91                    window.location = '/auth/login';
92                    return;
93
94                    // TODO: quick signup modals
95
96                    if($('#quick-signup-modal').length)
97                    {
98                        Fundable.UI.Modal.open('#quick-signup-modal');
99                    }
100                    else
101                    {
102                        Fundable.Common.errorMessage('You must have an account to do this.');
103                    }
104                }
105                else
106                {
107                    Fundable.Common.errorMessage('Whoops! There was an error processing this request.');
108                }
109
110            });
111        });
112
113        $('.btn.follow').addClass('initialized');
114
115    },
116    closeCustomModal: function (immediate) {
117        Fundable.UI.Modal.close(immediate);
118    },
119    openCustomModal:function(selector, immediate, locked) {
120        Fundable.UI.Modal.open(selector, immediate, locked);
121    },
122    unlockCustomModal:function()
123    {
124        Fundable.UI.Modal.unlock();
125    },
126    repositionCustomModal:function() {
127        var $modal = $('div.custom-modal:visible');
128        var $overlay = $modal.closest('div.custom-modal-overlay');
129        var $window = $(window);
130        if ($overlay) {
131            $overlay.height($window.height());
132            $overlay.width($window.width());
133        }
134        if ($modal) {
135            $modal.css({
136                top: parseInt($window.height() / 6) + 'px',
137                left: parseInt($window.width() / 2 - $modal.width() / 2) + 'px'
138            });
139        }
140    },
141    initBindableFields: function () {
142    	Fundable.UI.Bindables.init();
143
144    },
145    initNumberFields:function() {
146        Fundable.UI.NumberField.init();
147    },
148    initPercentFields: function () {
149        Fundable.UI.PercentField.init();
150    },
151    initPopoverFields: function () {
152        //
153    },
154    initMoneyFields:function() {
155        Fundable.UI.MoneyField.init();
156    },
157    initPhoneFields: function () {
158        Fundable.UI.PhoneField.init();
159    },
160    initCharacterLimitFields:function() {
161        Fundable.UI.CharacterLimitField.init();
162    },
163    ellipsize:function(string, maxLength)
164    {
165        if (string) {
166            if (string.length > maxLength) {
167                return string.substr(0, maxLength - 2) + '...';
168            }
169            else {
170                return string;
171            }
172        }
173    },
174    validate:function(container)
175    {
176        var thingsNotValid = [];
177        $(container).find('*[data-validations]').each(function () {
178            var thing = this;
179            var thingValue = $(thing).val();
180            var validations = $(thing).attr('data-validations').split(',');
181            $.each(validations, function (j, validation) {
182
183                var validationCommand = validation;
184                var validationParameter;
185                var result = false;
186
187                if(!Fundable.Validations[validationCommand])
188                {
189                    return false;
190                }
191
192                if (validation.indexOf('=') != -1) {
193                    validationCommand = validation.split('=')[0];
194                    validationParameter = validation.split('=')[1];
195                    result = Fundable.Validations[validationCommand](thingValue, validationParameter, thing);
196                }
197                else {
198                    result = Fundable.Validations[validationCommand](thingValue, null, thing);
199                }
200
201                if (!result) {
202                    thingsNotValid[thingsNotValid.length] = thing;
203                }
204
205            });
206        });
207        return thingsNotValid;
208    },
209    formatPhoneNumber:function(input)
210    {
211        if (!input)
212            return "";
213
214        input = input.replace(/[A-Za-z$\-()\s+]/g, "")
215
216        var output = input.substr(0, 3);
217        if (input.length >= 3) {
218            output += "-"+input.substr(3, 3);
219        }
220        if (input.length >= 6) {
221            output += "-"+input.substr(6, 4);
222        }
223        return output.toString();
224    },
225    equalsOneOf:function(value, compareToValues)
226    {
227        var match = false;
228        $.each(compareToValues, function (i, ctv) {
229            if (value == ctv) {
230                match = true;
231            }
232        });
233        return match;
234    },
235    loadMore:function(button)
236    {
237        if(!button) { return false; }
238
239        $(button).addClass('loading disabled');
240
241        var page = $(button).attr('data-page');
242        $(button).attr('data-page', parseInt(page)+1);
243        
244        var url = $(button).attr('data-url');
245        
246        url = url.replace('page=0', 'page='+page);
247        
248        var success = function(html)
249        {
250            if($.trim(html) == '0') { $(button).hide(); return; }
251
252            if(page == 0) { $(button).hide(); }
253            $($(button).attr('data-destination-selector')).append(html);
254            $(button).removeClass('loading disabled');
255            if($(button).attr('data-load-more-callback'))
256            {
257                return eval($(button).attr('data-load-more-callback'));
258            }
259        }
260
261        Fundable.Common.ajaxRequest('GET', url, {}, success);
262    },
263    successMessage:function(text)
264    {
265        return Fundable.UI.NotificationBar.success(text);
266    },
267    errorMessage:function(text)
268    {
269        return Fundable.UI.NotificationBar.error(text);
270    },
271    openLoadingModal:function(text)
272    {
273        if(!$('#global-loading-modal').length)
274        {
275            $('body').append('<div class="custom-modal-overlay"><div class="custom-modal paper" id="global-loading-modal" style="width:250;"><div class="loading-state" style="background-position:50% 45%;"><h3 style="padding-top:75px;">Test</h3></div></div></div>');
276        }
277        
278        if(text)
279        {
280            $('#global-loading-modal').find('h3').show().html(text);
281        }
282        else
283        {
284            $('#global-loading-modal').find('h3').hide();
285        }
286        Fundable.UI.Modal.open('#global-loading-modal');
287    },
288    closeLoadingModal:function()
289    {
290        Fundable.UI.Modal.close('#global-loading-modal');
291    },
292    isValidEmail: function (address) {
293        var reg = /^([A-Za-z0-9_\-\.\+])+\@([A-Za-z0-9_\-\.])+\.([A-Za-z]{2,20})$/;
294        if (reg.test(address) == false) {
295            return false;
296        }
297        else {
298            return true;
299        }
300    },
301    isValidPhoneNumber:function(num)
302    {
303        if(num) return true;
304        else return false;
305    },
306    initCustomFormElements: function () {
307        $('div.switch-input').off().on('click', function () {
308            if ($(this).hasClass('on')) {
309                $(this).removeClass('on').addClass('off');
310            }
311            else {
312                $(this).removeClass('off').addClass('on');
313            }
314        });
315    },
316    userIsInvestor: function (button) {
317        var url = $('#investor-opt-in').val();
318        $(button).addClass('loading').removeClass('primary');
319        var success = function (response) {
320            $('#investor-terms-modal').modal('hide');
321            $('div.investments').find('div.is-investor').show();
322            $('div.investments').find('div.not-investor').hide();
323        }
324        Fundable.Common.ajaxRequest('POST', url, {}, success);
325    },
326    ajaxRequest: function (method, url, data, success, error, fail) {
327        var headers = {};
328        method = method.toUpperCase();
329        
330        if (method == 'PUT' || method == 'DELETE') {
331            var headers = { 'x-http-method-override': method };
332            method = 'POST';
333        }
334
335        if (!data) {
336            data = {};
337        }
338        
339        if (!success) {
340            success = function () {}
341        }
342        
343        if (!error) {
344            error = function () {}
345        }
346
347        if (!fail) {
348            fail = function () {};
349        }
350        var callback = function (response) {
351            if (typeof response != 'object' && $.trim(response).substring(0, 1) != '<') {
352                // if it's not an object and doesn't start w/ markup, parse JOSN
353                response = $.parseJSON(response);
354            }
355            success(response);
356        }
357        $.ajax({
358            url: url,
359            type: method,
360            data: data,
361            headers: headers,
362            success: function (response) { callback(response); },
363            fail: fail
364        });
365
366        return;
367    },
368    prepareFundraise: function (CF) {
369        if (typeof CF == 'object') {
370            if (CF != null && CF.EndDate) {
371                var endDate = new Date(parseInt(CF.EndDate.substring(6)));
372                CF.EndDateFormatted = endDate.format("mmm d, yyyy, h:MM TT");
373            }
374        }
375
376        if (CF.StartDate) {
377            var startDate = new Date(parseInt(CF.StartDate.substring(6)));
378            CF.StartDateFormatted = startDate.format("mm/dd/yyyy");
379        }
380        else {
381            CF.StartDateFormatted = '';
382        }
383
384        CF.AmountRaisedFormatted = accounting.formatMoney(CF.Amou
384ntRaised);
385
386        CF.GoalAmountFormatted = accounting.formatMoney(CF.GoalAmount);
387
388        CF.PercentRaised = 100 * parseInt(CF.AmountRaised) / parseInt(CF.GoalAmount);
389        CF.PercentRaised = CF.PercentRaised.toFixed(0);
390        if (isNaN(CF.PercentRaised)) {
391            CF.PercentRaised = 0;
392        }
393        if (parseInt(CF.PercentRaised) > 100) {
394            CF.PercentRaisedVisual = 100;
395        }
396        else {
397            CF.PercentRaisedVisual = CF.PercentRaised;
398        }
399
400        return CF;
401    },
402    toggleSharePane: function () {
403        if ($('#global-share-pane').is(':visible')) {
404            $('#global-share-tab').css('left', 0);
405            $('#global-share-pane').hide();
406        }
407        else {
408            $('#global-share-tab').css('left', 70);
409            $('#global-share-pane').show();
410        }
411    },
412    
413    openMessageModal:function(button)
414    {
415        var data = {
416            recipients: $(button).attr('data-recipients'),
417            sender_company_id: $(button).attr('data-sender-company-id'),
418            subject: $(button).attr('data-subject'),
419            body: $(button).attr('data-body'),
420            messageable_type: $(button).attr('data-messageable-type'),
421            messageable_id: $(button).attr('data-messageable-id')
422        };
423
424        var url = $(button).attr('data-url');
425        if(!url)
426        {
427            url = '/messages/compose-modal'
428        }
429
430        if(!$('#message-modal').length)
431        {
432            $('body').append('<div class="custom-modal-overlay"><div class="custom-modal paper" id="message-modal" style="width:602px;"></div></div>');
433        }
434        
435        $('#message-modal').html('<div class="loading-state"></div>');
436        
437        Fundable.UI.Modal.open('#message-modal');
438
439        Fundable.Common.ajaxRequest('POST', url, data, function(html) {
440            $('#message-modal').html(html);
441            Fundable.UI.Modal.reposition();
442            Fundable.UI.Modal.focus();
443        });
444
445    },
446    openInvitationModal:function(button)
447    {
448        Fundable.UI.Modal.close();
449
450        var data = {
451            invitable_type: $(button).attr('data-invitable-type'),
452            invitable_id: $(button).attr('data-invitable-id'),
453            sent_by_company_id: $(button).attr('data-sent-by-company-id'),
454            sent_by_fundraise_id: $(button).attr('data-sent-by-fundraise-id'),
455            sent_by_community_id: $(button).attr('data-sent-by-community-id')
456        };
457
458        var url = $(button).attr('data-url');
459        if(!url)
460        {
461            url = '/invitation/compose-modal'
462        }
463
464        if(!$('#invitation-modal').length)
465        {
466            $('body').append('<div class="custom-modal-overlay"><div class="custom-modal paper" id="invitation-modal" style="width:602px;"></div></div>');
467        }
468        
469        $('#invitation-modal').html('<div class="loading-state"></div>');
470        
471        Fundable.UI.Modal.open('#invitation-modal');
472
473        Fundable.Common.ajaxRequest('POST', url, data, function(html) {
474            $('#invitation-modal').html(html);
475            Fundable.UI.Modal.reposition();
476            Fundable.UI.Modal.focus();
477        });
478    },
479    closeInvitationModal:function() {
480        Fundable.UI.Modal.close();
481    },
482    submitInvitationModal:function(form) {
483        if(!Fundable.Common.validateForm(form))
484        {
485            return false;
486        }
487
488        $(form).find('button').addClass('disabled').html('Sending...');
489        $(form).attr('id','invitation-to-send');
490        var data = Fundable.Utilities.getFormData('invitation-to-send');
491        $(form).removeAttr('id');
492
493        Fundable.Common.ajaxRequest('POST', $(form).attr('action'), data, function(response) {
494            $(form).find('button').removeClass('disabled').html('Send');
495            response = Fundable.Common.parseJson(response);
496            if(response.success)
497            {
498                Fundable.UI.Modal.close();
499                Fundable.Common.successMessage('Invitation has been sent!');
500
501                if(data.invitable_type == 'Fundable\\Entities\\InvestorPermission')
502                {
503                    Fundable.Company.EquityDashboard.loadInvestors();
504                }
505
506            }
507            else
508            {
509                alert('There was an error sending your invitation.');
510            }
511        });
512    },
513    submitMessageModal:function(form) {
514
515        if(!Fundable.Common.validateForm(form))
516        {
517            return false;
518        }
519
520        $(form).find('button').addClass('disabled').html('Sending...');
521        $(form).attr('id','message-to-send');
522        var data = Fundable.Utilities.getFormData('message-to-send');
523        $(form).removeAttr('id');
524
525        Fundable.Common.ajaxRequest('POST', $(form).attr('action'), data, function(response) {
526            $(form).find('button').removeClass('disabled').html('Send');
527            response = Fundable.Common.parseJson(response);
528            if(response.success)
529            {
530                Fundable.UI.Modal.close();
531                Fundable.Common.successMessage('Your message has been sent!');
532            }
533            else
534            {
535                alert('There was an error sending your message.');
536            }
537        });
538    },
539    closeMessageModal:function(button)
540    {
541        if(confirm('Are you sure? Any information enetered will be lost.'))
542        {
543            Fundable.UI.Modal.close();
544        }
545    },
546    validateForm:function(form)
547    {
548        $(form).find('div.field').removeClass('error');
549        $(form).find('input').removeClass('error');
550
551        var invalid = Fundable.Common.validate(form);
552        if(invalid && invalid.length)
553        {
554            $.each(invalid, function(i,el) {
555                $(el).closest('div.field').addClass('error');
556                $(el).addClass('error');
557            });
558            return false;
559        }
560        else
561        {
562            return true;
563        }
564    }
565}
566Fundable.Tracker = {
567    track:function(action, model, id) {
568        var data = {
569            action: action,
570            model: model,
571            id: id,
572            url: window.location
573        };
574        $.ajax({
575            url: '/tracking/track-action',
576            data: data,
577            type: "POST",
578            beforeSend: function(xhr) {
579                xhr.setRequestHeader('X-Fundable-Tracking-Url', window.location.href);
580            },
581            success: function(response) {
582                console.log(response);
583            }
584        });
585    },
586    trackComponentAction:function(action, componentKey) {
587        var data = {
588            action: action,
589            component_key: componentKey,
590            url: window.location.href
591        }
592
593        $.ajax({
594            url: '/tracking/track-component-action',
595            data: data,
596            type: "POST",
597            beforeSend: function(xhr) {
598                xhr.setRequestHeader('X-Fundable-Tracking-Url', data.url);
599            },
600            success: function(response) {
601                console.log(response);
602            }
603        });
604    }
605};
606
607Fundable.Validations = {
608    required: function (value) {
609       return (value != undefined && value != null && value != "")
610    },
611    checked: function(value, parameter, input) {
612        return ($(input).is(':checked'));
613    },
614    email: function (value) {
615        return Fundable.Common.isValidEmail(value);
616    },
617    phone: function (value) {
618        return Fundable.Common.isValidPhoneNumber(value);
619    },
620    minValue: function (value, minimum) {
621        return accounting.unformat(value) >= minimum;
622    },
623    maxValue: function( value, max) {
624        return accounting.unformat(value) <= max;
625    },
626    minLength: function (value, length) {
627        return value != undefined && value != null && value.length >= length;
628    },
629    maxLength: function (value, length) {
630        return value != undefined && value != null && value.length <= length;
631    }
632};

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.