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.