1$(document).ready(function(){ 2 3 $.ajaxSetup({ cache: false }); 4 5 var user_address = jQuery.parseJSON(localStorage.getItem('cached_customer_address')); 6 if(user_address){ 7 var address = user_address['full_address']; 8 var zip_code = user_address['zip_code']; 9 var address_type = user_address['address_type']; 10 $("#address_form #address").val(address); 11 $('#address_form input[name="zip_code"]').val(zip_code); 12 $('#address_form select[name="ADDRESS[TYPE]"]').val(address_type); 13 } 14 15 16 // Field Formats 17 if(($('.phone').length > 0) && (phone_mask != '')) $(".phone").mask(phone_mask, { placeholder: phone_placeholder, clearIfNotMatch: true }); 18 if(($('.mphone').length > 0) && (mobile_mask != '')) $(".mphone").mask(mobile_mask, { placeholder: mobile_placeholder, clearIfNotMatch: true }); 19 if(($('.mask-date').length > 0) && (date_mask != '')) $('.mask-date').mask(date_mask, { placeholder: date_placeholder, clearIfNotMatch: true }); 20 21 var clipboard = new ClipboardJS('.clipboard'); 22 clipboard.on('success', function(e) { 23 setTimeout("$('.clipboard').tooltip('hide');", 2000); 24 e.clearSelection(); 25 }); 26 27 $("#address_form").on("submit", function(){ 28 add_page_loader(); 29 30 var address = $('#address_form input[name="address"]').val(); 31 var zip_code = $('#address_form input[name="zip_code"]').val(); 32 var address_type = $('#address_form select[name="ADDRESS[TYPE]"]').val(); 33 34 var cached_address = {}; 35 cached_address.full_address = address; 36 cached_address.zip_code = zip_code; 37 cached_address.address_type = address_type; 38 try{ 39 if(cached_address.zip_code != '') 40 localStorage.setItem('cached_customer_address', JSON.stringify(cached_address)); 41 else 42 localStorage.setItem('cached_customer_address', JSON.stringify('')); 43 } 44 catch(e){} 45 }); 46 47 $(".clipboard").on('click', function(e){ 48 $(this).tooltip({title: "Link copied to clipboard!", placement: "bottom", trigger: "manual"}); 49 $(this).tooltip('show'); 50 }); 51 52 $('.selectpicker').selectpicker(); 53 54 $('a.menu-heading-toggle').on('click', function(e) { 55 e.preventDefault(); 56 57 toggle_menu_heading(this); 58 }); 59 60 $('a.filters-toggle').on('click', function(e) { 61 e.preventDefault(); 62 63 $(this).next('div.filter-items-toggle').slideToggle('fast'); 64 $(this).find('.filters-toggle-indicator').toggleClass('fa-plus-square-o fa-minus-square-o'); 65 }); 66 67 $('body').on('click', '.show-cart-modal', function(e) { 68 e.preventDefault(); 69 var pathname = window.location.pathname.toLowerCase(); //Current page path 70 var checkout_method = 'CASH'; 71 if (window.location.href.indexOf("group_order") > -1) { 72 group_order_show_cart_modal(); 73 } else { 74 if (pathname.indexOf('/order/checkout') > -1) { 75 if($("#CHECKOUTMETHOD").val().length > 0){ 76 checkout_method = $("#CHECKOUTMETHOD").val(); 77 } 78 $('#cart-modal').modal('show'); 79 $.post(base_url + "order/cart/true/" + checkout_method + "/0/1/1", function(data){ 80 $('#cart-modal .modal-body-content').html(data); 81 $('#cart-modal .modal-body-content').show(); 82 $('[data-toggle="tooltip"]').tooltip(); 83 $('#cart_content [data-toggle="popover"]').popover(); 84 //update_checkout_total_order(); 85 }); 86 } else { 87 $('#cart-modal').modal('show'); 88 $.get(base_url + "order/cart/0/0/0/1/1", function(data){ 89 $('#cart-modal .modal-body-content').html(data); 90 $('#cart-modal .modal-body-content').show(); 91 $('[data-toggle="tooltip"]').tooltip(); 92 $('#cart_content [data-toggle="popover"]').popover(); 93 /* $('#cart-modal .modal-footer').empty(); 94 $('#cart-modal').find('.cart-actions-wrapper').appendTo('#cart-modal .modal-footer');*/ 95 }); 96 } 97 } 98 }); 99 100 $('#cart-modal').on('hidden.bs.modal', function (e) { 101 $('#cart-modal .progress').show(); 102 $('#cart-modal .modal-body-content').html(''); 103 }) 104 105 $('#cart-modal').on('shown.bs.modal', function (e) { 106/* $('#cart-modal .modal-body').css('height', $(window).height()*0.8); 107 $('#cart-modal .modal-body').css('max-height', $(window).height()*0.8 - 100);*/ 108 $('#cart-modal .modal-body').show(); 109 $('#cart-modal .progress').hide(); 110 }) 111
112 $('.store-link img.media-object').error(function() { $(this).hide() }); 113 114/* 115 // Disabled these hashes on the URL 8/8/17. 116 $(".modal").on("shown.bs.modal", function() { // any time a modal is shown 117 if (window.location.href.indexOf('mobile.php') < 0) { 118 var urlReplace = "#" + $(this).attr('id'); // make the hash the id of the modal shown 119 history.pushState(null, null, urlReplace); // push state that hash into the url 120 } 121 }); 122*/ 123 // Hide DLC breadcrumbs if on single embed page. 124 if (window.location.href.indexOf('single.php') > 0) { 125 $('#page_subheader').addClass('hidden'); 126 } 127 128 // If a pushstate has previously happened and the back button is clicked, hide any modals. 129 $(window).on('popstate', function() { 130 $(".modal").modal('hide'); 131 }); 132 133 // Remove the hash when modal is closed and user did not click back button. 134 $(".modal").on("hide.bs.modal", function() { 135 if(window.location.hash) { 136 //history.pushState('', document.title, window.location.pathname); 137 //history.back(1); 138 } 139 }); 140 141 if (session_user) { 142 var logged_in_user = getCookie('logged_in_user'); 143 $('.not-logged-in').addClass('hidden'); 144 $('.logged-in').removeClass('hidden'); 145 $('.account-name').html(logged_in_user.replace('+', ' ')); 146 } else { 147 $('.not-logged-in').removeClass('hidden'); 148 $('.logged-in').addClass('hidden'); 149 } 150 151}); 152 153$(document).on("click", "button[data-loading-text]", function(event){ 154 $(this).button('loading'); 155}); 156 157var print_window; 158function print(URL, title){ 159 160 print_window = window.open(URL, title, 'toolbar=0,scrollbars=1,location=0,statusbar=0,menubar=0,resizable=0,width=600,height=600,left = 390,top = 212'); 161 setTimeout('print_window.print();', 1000); 162} 163 164function getCookie(key) { 165 166 var keyValue = document.cookie.match('(^|;) ?' + key + '=([^;]*)(;|$)'); 167 return keyValue ? keyValue[2] : null; 168} 169 170function toggle_menu_heading(heading) { 171 172 $(heading).find('.menu-heading-toggle-indicator i').toggleClass('fa-plus-square-o fa-minus-square-o'); 173 if($(heading).parent().find('div.menu-items-toggle').is(':visible')) { 174 $(heading).parent().find('div.menu-items-toggle').slideToggle('fast'); 175 } 176 else { 177 // scrollTo plugin causes mobile app to scroll to top on each menu heading click, swapped to jquery native function 178 $('html, body').animate({ 179 scrollTop: $(heading).parent().offset().top - 70 180 }, 250); 181 182 //$(heading).parent().ScrollTo({ 183 // onlyIfOutside: true, 184 // offsetTop: 60 185 //}); 186 187 $(heading).parent().find('div.menu-items-toggle').slideToggle('fast'); 188 } 189} 190 191function toggle_restaurant_filters() { 192 193 if($('#restaurant_filters').is(':visible')) { 194 195 $('#restaurant_filters').addClass('hidden-xs hidden-sm'); 196 $('#restaurant_filter_show').show(); 197 $('#restaurant_filter_hide').hide(); 198 } 199 else { 200 201 $('#restaurant_filters').removeClass('hidden-xs hidden-sm'); 202 $('#restaurant_filter_show').hide(); 203 $('#restaurant_filter_hide').show(); 204 } 205} 206 207// array shuffle 208Array.prototype.shuffle = function() { 209 var input = this; 210 211 for (var i = input.length-1; i >=0; i--) { 212 213 var randomIndex = Math.floor(Math.random()*(i+1)); 214 var itemAtIndex = input[randomIndex]; 215 216 input[randomIndex] = input[i]; 217 input[i] = itemAtIndex; 218 } 219 return input; 220} 221 222(function ($) { 223 // function to quickly add bootstrap dropdown menus to navigation bar 224 $.fn.add_dropdown = function(menu) { 225 this.addClass('dropdown'); 226 this.find('a').addClass('dropdown-toggle').attr('data-toggle', 'dropdown').append(' <span class="caret"></span>'); 227 this.append('<ul class="dropdown-menu">'); 228 for(var link in menu) { 229 this.find('ul.dropdown-menu').append('<li><a href="' + link + '">' + menu[link] + '</a><li>'); 230 } 231 this.append('</ul>'); 232 233 return this; 234 } 235 236 $.fn.address_autocomplete = function(options, callback) { 237 238 var use_country_code = 'us'; 239 if(country_code) use_country_code = country_code; 240 241 // Disable use under certain criteria. 242 if(use_country_code == 'mm') return; 243 if(use_country_code == 'pa') return; 244 if(use_country_code == 'bm') return; 245 246 var settings = $.extend({ 247 autocomplete_type: 'address', // set type of autocomplete 248 country: use_country_code, // set the country restriction 249 use_prediction: true, // use the google prediction service? 250 auto_submit: true, // auto submit form on address selection? 251 container_div: 'div.autocomplete_container', // name of container 252 bounds_circle: null, // bounding circle 253 cache_address: true // cache address to local storage 254 }, options); 255 256 $(this).each(function() { 257 258 var el = $(this); 259 260 var address_form = el.is('form') ? el : el.closest('form'); 261 var address_div = el.closest(settings.container_div); 262 263 var hnd = (address_div.length > 0) ? address_div : address_form; 264 265 // find the elements in the address form 266 var address_field = hnd.find('input[name="address"], input#address, input.address'); 267 var city_field = hnd.find('input[name="city"], input#city, input.city'); 268 var state_field = hnd.find('input[name="state"], input#state, select#state, input.state, select.state'); 269 var zipcode_field = hnd.find('input[name="zip_code"], input#zip_code, input.zip_code'); 270 var address_type_field = hnd.find('select[name="ADDRESS[TYPE]"], select#address_type'); 271 272 $(address_field).attr('autocomplete', 'off'); 273 274 $(address_field).typeahead({ 275 276 fitToElement: true, 277 items: 10, 278 //minLength: 5, 279 delay: 350, 280 changeInputOnSelect: false, 281 autoSelect: true, 282 selectOnBlur: false, 283 284 source: function(query, typeahead) { 285 286//console.log(query); 287 // Don't query if not enough. 288 if((query.length < 5) && !query.includes(' ')) return; 289 290 return $.getJSON(base_url + 'order/autocomplete/address/' + encodeURIComponent(query), function(data) { 291 292 var src = null; 293 var locations = []; 294 $.each(data, function(index, address) { 295 296 src = address.src; 297 locations.push({ id: address.reference, name: address.autocomplete_display1 + '<br/>' + address.autocomplete_display2, contains_details: address.contains_details, full_address: address.full_address, city: address.city, state: address.state, zipcode: address.zipcode, query: address.query, src: src }); 298 }); 299 300//console.log(locations); 301 typeahead(locations); 302 if(src == 'google') $('.typeahead').append('<img style="float: right; height: 15px; margin-right: 10px; margin-top: 10px;
302" src="https://maps.gstatic.com/mapfiles/api-3/images/powered-by-google-on-white3_hdpi.png" />'); 303 }); 304 }, 305 306 matcher: function(item) { 307 308 return true; 309 }, 310 311 displayText: function(obj, text_only) { 312 313 if(text_only) return obj.full_address; 314 return '<span class="address_autocomplete_entry"><i class="fa fa-map-marker"></i>' + obj.name + '</span>'; 315 }, 316 317 afterSelect: function(obj) { 318 319//console.log('selected');console.log(obj); 320 321 // Some sources do not require an additional lookup. 322 if(obj.contains_details) { 323 324 if(obj.zipcode != '') zipcode_field.val(obj.zipcode); 325 if(obj.full_address != '') address_field.val(obj.full_address); 326 if(obj.city != '' && city_field.length) city_field.val(obj.city); 327 if(obj.state != '' && state_field.length) state_field.val(obj.state); 328 if(obj.type != '') address_type_field.val(obj.type); 329 if(obj.full_address != '' && obj.zipcode != '' && settings.auto_submit) address_form.submit(); 330 return; 331 } 332 333 $.getJSON(base_url + 'order/autocomplete/details/' + encodeURIComponent(obj.id) + '/' + encodeURIComponent(obj.src), function(data) { 334 335//console.log('details');console.log(data); 336 337 // TODO: need all of that intl logic - move into helper? 338 var zipcode = data.zip; 339 var full_address = data.address1; 340 var city = data.city; 341 var address_type = data.type; 342 var state = data.state; 343 344 if(zipcode != '') zipcode_field.val(zipcode); 345 if(full_address != '') address_field.val(full_address); 346 if(city != '' && city_field.length) city_field.val(city); 347 if(state != '' && state_field.length) { if(state_field.attr('name') == undefined) state_field.attr('name', 'state'); state_field.val(state); } 348 // Auto-select address type if detected and field exists 349 if(address_type && address_type_field.length) { 350 address_type_field.val(address_type).trigger('change'); 351 // Trigger selecttype() function if it exists (enables save button) 352 if(typeof selecttype === 'function') { 353 selecttype(); 354 } 355 } 356 357 if(full_address != '' && zipcode != '' && settings.auto_submit) { 358 359 address_form.append('<input type="hidden" name="update_order_params" value="true"/>'); 360 address_form.submit(); 361 } 362 }); 363 } 364 }); 365 }); 366 367return; 368///// GOOGLE WIDGET VERSION BELOW 369 370 // default settings 371 var settings = $.extend({ 372 autocomplete_type: 'address', // set type of autocomplete 373 country: use_country_code, // set the country restriction 374 use_prediction: true, // use the google prediction service? 375 auto_submit: false, // auto submit form on address selection? 376 container_div: 'div.autocomplete_container', // name of container 377 bounds_circle: null, // bounding circle 378 cache_address: true // cache address to local storage 379 }, options); 380 381 if((places_location != '') && (places_radius != '')) { 382 383 var pieces = places_location.split(','); 384 settings.bounds_circle = new google.maps.Circle({ center: new google.maps.LatLng(pieces[0], pieces[1]), radius: parseInt(places_radius) }); 385 } 386 387 // loop through each object and apply autocomplete function 388 this.each(function() { 389 // variables for address autocomplete 390 var address_autocomplete; 391 var address_autocomplete_options = { componentRestrictions: { country: settings.country } }; 392 var address_autocomplete_service; 393 394 // get element and it's container (if any) 395 var el = $(this); 396 397 var address_form = el.is('form') ? el : el.closest('form'); 398 var address_div = el.closest(settings.container_div); 399 400 // if more than one autocomplete field in a form, we need to get a handle to the container 401 var hnd = (address_div.length > 0) ? address_div : address_form; 402 403 // find the elements in the address form 404 var address_field = hnd.find('input[name="address"], input#address, input.address'); 405 var city_field = hnd.find('input[name="city"], input#city, input.city'); 406 var state_field = hnd.find('input[name="state"], input#state, select#state, input.state, select.state'); 407 var zipcode_field = hnd.find('input[name="zip_code"], input#zip_code, input.zip_code'); 408 var address_type_field = hnd.find('select[name="ADDRESS[TYPE]"], select#address_type'); 409 410 // address prediction programmatically gets first result from autocomplete widget 411 var address_prediction = function(predictions, status) { 412 if (status == 'OK') { 413console.log(predictions); 414 var place_id = predictions[0].place_id; 415 var places = new google.maps.places.PlacesService(address_field[0]); 416 places.getDetails({ placeId: place_id }, 417 function result(address_detail, places_service_status) { 418 populate_address_fields(address_detail); 419 } 420 ); 421 } 422 } 423 424 // populate the address/zip fields 425 var populate_address_fields = function(place_detail) { 426 // see if we're passing in a place object or if we need to get it from the autocomplete widget 427 var place = (typeof place_detail === 'undefined') ? address_autocomplete.getPlace() : place_detail; 428 var place_type = (place.types) ? place.types[0] : ''; 429 var address_components; 430 var full_address = ''; 431 var city = ''; 432 var state = ''; 433 var zipcode = ''; 434 435 // determine what type of place this address is 436 switch(place_type) { 437 case 'route': 438 address_components = { street_number: 'long_name', route: 'long_name', locality: 'short_name', postal_code: 'short_name', political: 'short_name', administrative_area_level_1: 'short_name', administrative_area_level_2: 'short_name', neighborhood: 'short_name', sublocality_level_1: 'short_name', postal_code_prefix: 'long_name' }; 439 break; 440 441 default: 442 address_components = { street_number: 'long_name', route: 'long_name', postal_code: 'short_name', political: 'short_name', administrative_area_level_1: 'short_name', administrative_area_level_2: 'short_name', locality: 'short_name', neighborhood: 'short_name', sublocality_level_1: 'short_name', postal_code_prefix: 'long_name' }; 443 break; 444 } 445 446 // get each component of the address from the place details and update the corresponding field on the form. 447 if (place.address_components) { 448 449 var has_street_number = false;
450 451 for(var i = 0; i < place.address_components.length; i++) { 452 453 var address_type = place.address_components[i].types[0]; 454 455 if (address_components[address_type]) { 456 var val = place.address_components[i][address_components[address_type]]; 457 458 if(address_type == "street_number") { 459 has_street_number = true; 460 if (full_address == '') 461 full_address = val; 462 else 463 full_address = val + " " + full_address; 464 } 465 else if(address_type == "route") { 466 467 if(use_country_code == 'es') 468 full_address = val + ', ' + full_address; 469 else 470 full_address += " " + val; 471 } 472 else if(address_type == "locality") { 473 474 if(use_country_code == 'ie') { 475 476 if(full_address == '') full_address = val; 477 } 478 else city = val; 479 } 480 else if((address_type == "political") || (address_type == "administrative_area_level_1")) { 481 482 if(use_country_code != 'ie') 483 state = val; 484 } 485 else if(address_type == "postal_code") { 486 zipcode = val; 487 } 488 else if(address_type == "postal_code_prefix") { 489 zipcode = val; 490 } 491 else if(address_type == "postal_town") { 492 zipcode = val; 493 } 494 else if(address_type == "sublocality_level_1") { 495 if(use_country_code == 'mm') zipcode = val; 496 } 497 else if(address_type == "neighborhood") { 498 499 if(use_country_code == 'ie') { 500 501 if(full_address == '') full_address = val; 502 } 503 else if(zipcode == '') zipcode = val; 504 } 505 else if(address_type == "administrative_area_level_2") { 506 507 if(use_country_code == 'ie') 508 zipcode = val; 509 else if(use_country_code == 'mm') 510 zipcode = val.replace(' Township', ''); 511 } 512 } 513 } 514 } 515 516 // Non-US: If no street number was received, parse it from the input. 517 if((use_country_code != 'us') && !has_street_number) { 518 519 var user_input = address_field.val().toUpperCase(); 520 var sa_pos = user_input.indexOf(full_address.toUpperCase()); 521 if(sa_pos != -1) { 522 523 var sa_data = user_input.substr(0, sa_pos); 524 full_address = sa_data + ' ' + full_address.trim(); 525 } 526 } 527 528 if(use_country_code == 'ph') zipcode = ''; 529 530 // populate the address form 531 if (zipcode != '') zipcode_field.val(zipcode); 532 if (full_address != '') address_field.val(full_address); 533 if (city != '' && city_field.length) city_field.val(city); 534 if (state != '' && state_field.length) state_field.val(state); 535 if (type != '') address_type_field.val(type); 536 537 if (settings.cache_address) { 538 var cached_address = {}; 539 cached_address.full_address = full_address; 540 cached_address.zip_code = zipcode; 541 cached_address.address_type = type; 542 543 localStorage.setItem('cached_customer_address', JSON.stringify(cached_address)); 544 } 545 546 // check if we are autosubmitting the form 547 if (full_address != '' && zipcode != '' && settings.auto_submit) address_form.submit(); 548 if (typeof callback === 'function') callback(); 549 550 return false; 551 } 552 553 // check to make sure the element we are bound to is actually present 554 var input_field = el.is('form') ? address_field : el; 555 if (input_field && (input_field.length > 0)) { 556 if (settings.autocomplete_type == 'address') { 557 // get the autocomplete widget 558 address_autocomplete = new google.maps.places.Autocomplete(input_field[0], address_autocomplete_options); 559 if(settings.bounds_circle) address_autocomplete.setBounds(settings.bounds_circle.getBounds()); 560 } 561 562 563 if (settings.autocomplete_type == 'establishment') { 564 // get the autocomplete widget 565 address_autocomplete = new google.maps.places.Autocomplete(input_field[0], { types: ['establishment'] }); 566 var input_val = input_field.val().split(','); 567 input_field.val(input_val[0]); 568 } 569 570 // listen for enter key 571 google.maps.event.addDomListener(input_field[0], 'keyup', function(e) { 572 if (e.keyCode === 13) { 573 e.preventDefault(); 574 e.stopPropagation(); 575 e.stopImmediatePropagation(); 576 577 if (settings.use_prediction) { 578 // if user hits enter key, we get the first result from the autocomplete widget programmatically 579 address_autocomplete_service = new google.maps.places.AutocompleteService(); 580 address_autocomplete_service.getPlacePredictions({ input: input_field.val() }, address_prediction); 581 } 582 583 return false;
584 } 585 }); 586 587 // listen for an address change 588 address_autocomplete.addListener('place_changed', function() { 589 populate_address_fields(); 590 }); 591 } 592 }); 593 594 return this; 595 } 596 597 //pass in just the context as a $(obj) or a settings JS object 598 $.fn.autogrow = function(opts) { 599 var that = $(this).css({overflow: 'hidden', resize: 'none'}), //prevent scrollies 600 selector = that.selector, 601 defaults = { 602 context: $(document), //what to wire events to 603 animate: true, //if you want the size change to animate 604 speed: 200, //speed of animation 605 fixMinHeight: true, //if you don't want the box to shrink below its initial size 606 cloneClass: 'autogrowclone', //helper CSS class for clone if you need to add special rules 607 onInitialize: false //resizes the textareas when the plugin is initialized 608 }; 609 610 opts = $.isPlainObject(opts) ? opts : {context: opts ? opts : $(document)}; 611 opts = $.extend({}, defaults, opts); 612 that.each(function(i, elem){ 613 var min, clone; 614 elem = $(elem); 615 //if the element is "invisible", we get an incorrect height value 616 //to get correct value, clone and append to the body. 617 if (elem.is(':visible') || parseInt(elem.css('height'), 10) > 0) {
618 min = parseInt(elem.css('height'), 10) || elem.innerHeight(); 619 } else { 620 clone = elem.clone() 621 .addClass(opts.cloneClass) 622 .val(elem.val()) 623 .css({ 624 position: 'absolute', 625 visibility: 'hidden', 626 display: 'block' 627 }); 628 $('body').append(clone); 629 min = clone.innerHeight(); 630 clone.remove(); 631 } 632 if (opts.fixMinHeight) { 633 elem.data('autogrow-start-height', min); //set min height 634 } 635 elem.css('height', min); 636 637 if (opts.onInitialize && elem.length) { 638 resize.call(elem[0]); 639 } 640 }); 641 opts.context.on('keyup paste', selector, resize); 642 643 function resize (e){ 644 var box = $(this), 645 oldHeight = box.innerHeight(), 646 newHeight = this.scrollHeight, 647 minHeight = box.data('autogrow-start-height') || 0, 648 clone; 649 650 if (oldHeight < newHeight) { //user is typing 651 this.scrollTop = 0; //try to reduce the top of the content hiding for a second 652 opts.animate ? box.stop().animate({height: newHeight}, opts.speed) : box.innerHeight(newHeight); 653 } else if (!e || e.which == 8 || e.which == 46 || (e.ctrlKey && e.which == 88)) { //user is deleting, backspacing, or cutting 654 if (oldHeight > minHeight) { //shrink! 655 //this cloning part is not particularly necessary. however, it helps with animation 656 //since the only way to cleanly calculate where to shrink the box to is to incrementally 657 //reduce the height of the box until the $.innerHeight() and the scrollHeight differ. 658 //doing this on an exact clone to figure out the height first and then applying it to the 659 //actual box makes it look cleaner to the user 660 clone = box.clone() 661 //add clone class for extra css rules 662 .addClass(opts.cloneClass) 663 //make "invisible", remove height restriction potentially imposed by existing CSS 664 .css({position: 'absolute', zIndex:-10, height: ''}) 665 //populate with content for consistent measuring 666 .val(box.val()); 667 box.after(clone); //append as close to the box as possible for best CSS matching for clone 668 do { //reduce height until they don't match 669 newHeight = clone[0].scrollHeight - 1; 670 clone.innerHeight(newHeight); 671 } while (newHeight === clone[0].scrollHeight); 672 newHeight++; //adding one back eliminates a wiggle on deletion 673 clone.remove(); 674 box.focus(); // Fix issue with Chrome losing focus from the textarea. 675 676 //if user selects all and deletes or holds down delete til beginning 677 //user could get here and shrink whole box 678 newHeight < minHeight && (newHeight = minHeight); 679 oldHeight > newHeight && opts.animate ? box.stop().animate({height: newHeight}, opts.speed) : box.innerHeight(newHeight); 680 } else { //just set to the minHeight 681 box.innerHeight(minHeight); 682 } 683 } 684 } 685 return that; 686 } 687}(jQuery)); 688 689function seconds_to_HMS(secs, word_format) { 690 691 var num_hours = Math.floor(secs / 3600); 692 var num_minutes = Math.floor((secs - (num_hours * 3600)) / 60); 693 var secs_remain = Math.round(secs - ((num_hours * 3600) + (num_minutes * 60))); 694 var rv = ''; 695 696 if(word_format) { 697 698 699 if(num_hours > 0) rv = num_hours + ' ' + pluralize_word('hour', num_hours); 700 if(num_minutes > 0) { 701 702 if(rv != '') rv += ' '; 703 rv += num_minutes + ' ' + pluralize_word('minute', num_minutes); 704 } 705 if(secs_remain > 0) { 706 707 if(rv != '') rv += ' '; 708 rv += secs_remain + ' ' + pluralize_word('second', secs_remain); 709 } 710 } 711 else { 712 713 if(num_minutes < 10) num_minutes = "0" + num_minutes; 714 if(secs_remain < 10) secs_remain = "0" + secs_remain; 715 716 if(num_hours > 0) rv = num_hours + ':' + num_minutes + ':' + secs_remain; 717 else if(parseInt(num_minutes) > 0) rv = '00:' + num_minutes + ':' + secs_remain; 718 else rv = '00:00:' + secs_remain; 719 } 720 721 return rv; 722} 723 724function pluralize_word(base, num) { 725 726 if(num == 1) return base; 727 return base + 's'; 728} 729 730var loader_enabled = false; 731function add_page_loader() { 732 733 if(!loader_enabled) { 734 735 loader_enabled = true; 736 return; 737 } 738 739 var is_safari = false; 740 try { 741 742 is_safari = ((navigator.userAgent.indexOf("Safari") > -1) && (navigator.userAgent.indexOf("Chrome") == -1)); 743 } 744 catch(ex) { 745 } 746 747 // Don't use the loader if Safari. 748 if(is_safari) return; 749 $('#page-loader').show(); 750} 751 752function remove_page_loader() { 753 $('#page-loader').fadeOut("slow"); 754} 755 756function format_money(amount) { 757 758 var decimals = 2; 759 if(country_code == 'mm') decimals = 0; 760 761 return currency_symbol + amount.toFixed(decimals); 762} 763 764function levenshtein_ratio(s1, s2) { 765 let max_len = (s1.length > s2.length) ? s1.length : s2.length; 766 return Math.round((1 - levenshteinDistance(s1, s2) / max_len) * 100); 767} 768 769function levenshteinDistance(str1 = '', str2 = '') { 770 const track = Array(str2.length + 1).fill(null).map(() => Array(str1.length + 1).fill(null)); 771 772 for (let i = 0; i <= str1.length; i += 1) { 773 track[0][i] = i; 774 } 775 776 for (let j = 0; j <= str2.length; j += 1) { 777 track[j][0] = j; 778 } 779 780 for (let j = 1; j <= str2.length; j += 1) { 781 for (let i = 1; i <= str1.length; i += 1) { 782 const indicator = str1[i - 1] === str2[j - 1] ? 0 : 1; 783 track[j][i] = Math.min( 784 track[j][i - 1] + 1, //deletion 785 track[j - 1][i] + 1, //insertion 786 track[j - 1][i - 1] + indicator, //substitution 787 ); 788 } 789 } 790 791 return track[str2.length][str1.length]; 792} 793 794function stringSimilarity(str1, str2, gramSize = 2) { 795 function getNGrams(s, len) { 796 s = ' '.repeat(len - 1) + s.toLowerCase() + ' '.repeat(len - 1); 797 let v = new Array(s.length - len + 1); 798 for (let i = 0; i < v.length; i++) { 799 v[i] = s.slice(i, i + len); 800 } 801 return v; 802 } 803 804 if (!str1?.length || !str2?.length) { return 0.0; } 805 806 let s1 = str1.length < str2.length ? str1 : str2; 807 let s2 = str1.length < str2.length ? str2 : str1; 808 809 let pairs1 = getNGrams(s1, gramSize); 810 let pairs2 = getNGrams(s2, gramSize); 811 let set = new Set(pairs1); 812 813 let total = pairs2.length; 814 let hits = 0; 815 for (let item of pairs2) { 816 if (set.delete(item)) { 817 hits++; 818 } 819 } 820 821 return (hits / total) * 100; 822} 823 824function show_deal_item(deal_id) { 825 // Find the item container div using the deal_id 826 var $item = $("#order_restaurant--menu_item_" + deal_id); 827 var debug = false 828 829 if ($item.length > 0) { 830 if(debug) console.log("Found deal item:", $item); 831 832 // Find the closest parent container that has an onclick event (assumed to be the clickable container) 833 var $clickableContainer = $item.closest(".order_restaurant--menu_item_container"); 834 835 if ($clickableContainer.length > 0) { 836 if(debug) console.log("Triggering click on:", $clickableContainer); 837 $clickableContainer.click(); 838 } else { 839 if(debug) console.warn("No clickable container found for deal_id:", deal_id); 840 } 841 } else { 842 if(debug) console.warn("Deal item not found for deal_id:", deal_id); 843 } 844} 845
846// Globally-UI-Hamburger-menu-position-changes 847jQuery(document).ready(function($){ 848$('#page-loader').on('click', function() { 849 $('body').removeClass('block-scroll sidemenu-active'); 850 $('.header-menu-mobile').removeClass('active'); 851}); 852});
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.