1$(document).ready(function () { 2 var service = new google.maps.places.AutocompleteService(); 3 $("form.navbar-search").submit(function (e) { 4 if (e.preventDefault) e.preventDefault(); 5 return false; 6 }); 7 $("#destination-search").typeahead( 8 { 9 hint: false, 10 highlight: true, 11 minLength: 2, 12 async: true, 13 displayKey: "description", 14 }, 15 { 16 source: function (query, sync, async) { 17 if (query) { 18 var matches = []; 19 service.getPlacePredictions( 20 { 21 input: query, 22 }, 23 function (predictions, status) { 24 if (status == google.maps.places.PlacesServiceStatus.OK) { 25 predictions.forEach(function (prediction) { 26 if ( 27 prediction.types.length === 1 && 28 prediction.types.includes("establishment") 29 ) 30 return; 31 matches.push(prediction); 32 }); 33 async(matches); 34 } 35 } 36 ); 37 } 38 }, 39 templates: { 40 suggestion: function (data) { 41 return "<span>" + data.description + "</span>"; 42 }, 43 }, 44 displayKey: "label", 45 } 46 ); 47 $("#destination-search").bind("typeahead:selected", function (e, data) { 48 $.get( 49 "/api/v4/boats/search/?place_id=" + data.place_id, 50 function (data) { 51 window.top.location.href = data.search_route; 52 }, 53 "json" 54 ); 55 }); 56}); 57 58$(document).ready(function () { 59 $.get("/api/v4/auth/user/", function (data, status) { 60 if (status == "success" && data && data.pk) { 61 $("#user-name").text(data.first_name + " " + data.last_name); 62 if (data.photo_url) $("#user-avatar").attr("src", data.photo_url); 63 $("#user-menu").toggle(true); 64 } 65 }); 66 $("#share-copy").click(function () { 67 setTimeout(function () { 68 $("#share-link").select(); 69 document.execCommand("copy"); 70 }, 100); 71 }); 72 $("#share-link").click(function (e) { 73 $(this).select(); 74 document.execCommand("copy"); 75 }); 76 77 // Trip categories 78 var view = $("div.scroll"); 79 var tileSize = 209; 80 var tileScroll = tileSize * 2; 81 var count = $("div.trip-categories ul li").length; 82 var sliderLimit = "-" + count * tileSize; 83 84 view.css("width", Math.abs(sliderLimit + 20 + "px")); 85 86 $(".arrow-right", $("div.trip-categories")).click(function () { 87 var sliderEnd = "-" + (count * tileSize - $("div.trip-categories").width()); 88 var currentPosition = parseInt(view.css("left")); 89 90 if (currentPosition < sliderEnd) { 91 view.stop(false, true).animate({ left: 0 }, { duration: 400 }); 92 $(".arrow-left", $("div.trip-categories")).hide(); 93 } else if (currentPosition >= sliderLimit) { 94 view 95 .stop(false, true) 96 .animate({ left: "-=" + tileScroll + "px" }, { duration: 400 }); 97 $(".arrow-left", $("div.trip-categories")).show(); 98 if (currentPosition - tileScroll <= sliderEnd) { 99 $(this).hide(); 100 } 101 } 102 }); 103 104 $(".arrow-left", $("div.trip-categories")) 105 .click(function () { 106 var sliderEnd = 107 "-" + (count * tileSize - $("div.trip-categories").width()); 108 var currentPosition = parseInt(view.css("left")); 109 110 if (currentPosition < 0) { 111 view 112 .stop(false, true) 113 .animate({ left: "+=" + tileScroll + "px" }, { duration: 400 }); 114 $(".arrow-right", $("div.trip-categories")).show(); 115 if (currentPosition + tileScroll < 0) { 116 $(this).show(); 117 } else { 118 $(this).hide(); 119 } 120 } else { 121 $(this).hide(); 122 } 123 }) 124 .hide(); 125 126 $("a", $("div.post-content")).click(function (e) { 127 if ( 128 $(this).attr("href").indexOf(".getmyboat.com") == -1 && 129 $(this).attr("href").charAt(0) != "#" 130 ) { 131 window.open($(this).attr("href"), "_blank"); 132 e.preventDefault(); 133 return false; 134 } 135 }); 136}); 137 138$(document).ready(function () { 139 // Single listings 140 $("div.listing", $("div.listing-single")).each(function (i, el) { 141 var id = $(el).data("listing-id"); 142 $.getJSON("/api/v4/boats/" + id + "/?strip_tags=true", function (data) { 143 drawSingleListing(el, data); 144 }); 145 }); 146 147 // Multi listings 148 var listing_ids = []; 149 $("div.listing", $("div.listing-multiple")).each(function (i, el) { 150 listing_ids.push("boat_ids[]=" + $(el).data("listing-id")); 151 }); 152 if (listing_ids.length == 0) return; 153 $.getJSON( 154 "/api/v4/boats/many/?strip_tags=true&" + listing_ids.join("&"), 155 function (data) { 156 var container = $("div.listing-multiple"); 157 $.each(data, function (i, listing) { 158 var el = $( 159 'div.listing[data-listing-id="' + listing.id + '"]', 160 container 161 ); 162 drawMultipleListings(el, listing); 163 }); 164 } 165 ); 166}); 167 168$(document).ready(function () { 169 const INITIAL_LANDING_PAGE_KEY = 'initial_landing_page'; 170 171 if (!localStorage.getItem(INITIAL_LANDING_PAGE_KEY)) { 172 const initialLandingPage = createInitialLandingPage({ 173 location: window.location, 174 referrer: document.referrer.toLowerCase(), 175 }); 176 try { 177 window.localStorage.setItem(INITIAL_LANDING_PAGE_KEY, JSON.stringify(initialLandingPage)); 178 } catch (e) { 179 // Fail silently 180 } 181 } 182}); 183 184function standardiseImageSize(url) { 185 let urlObj = new URL(url); 186 urlObj.searchParams.delete('w'); 187 urlObj.searchParams.delete('h'); 188 urlObj.searchParams.set('w', '210'); 189 urlObj.searchParams.set('h', '136'); 190 urlObj.searchParams.set('fit', 'clamp'); 191 urlObj.searchParams.set('crop', 'edges'); 192 return urlObj.toString(); 193} 194 195function drawMultipleListings(el, data) { 196 var headline = $('<h6 class="headline"></h6>').append( 197 $('<a target="_blank" href="/trips/' + data.id + '/"></a>').text( 198 data.headline 199 ) 200 ); 201 // Location 202 var location = $('<span class="location"></span>'); 203 location.text( 204 `${data.category_string} in ${data.city} - ${data.capacity} guests` 205 ); 206 207 // Photo 208 var photo = $( 209 '<div class = "photo"><a target="_blank" href="/trips/' + 210 data.id + 211 '/"><img src="' + 212 standardiseImageSize(data.photo_url) + 213 '" alt="' + 214 data.headline + 215 '"/></a></div>' 216 ); 217 218 var price = $("<div class='price'></div>").append( 219 $("<span class='amount' ></span>").text( 220 `${ 221 data.search_price_nested.symbol 222 }
222${data.search_price_nested.price.toLocaleString()}` 223 ), 224 $('<span class="label"></span>').text(data.prices[0].price_unit) 225 ); 226 227 var wrapped = $('<div class="wrapper">').append(photo); 228 229 // Combine elements 230 $(el).append(wrapped, location, headline, price); 231} 232 233function drawListingStars(el, rating) { 234 var stars = ""; 235 var avg = Math.ceil(rating); 236 for (var i = 1; i < 6; i++) { 237 if (i <= rating) stars += '<span class="gold">â</span>'; 238 else stars += "<span>â</span>"; 239 } 240 $(el).append($(stars)); 241} 242 243function drawSingleListing(el, data) { 244 var headline = $('<h3 class="headline"></h3>').append( 245 $('<a target="_blank" href="/trips/' + data.id + '/"></a>').text( 246 data.headline 247 ) 248 ); 249 250 Location; 251 var location_breadcrumbs = []; 252 if (data.country) 253 location_breadcrumbs.push( 254 $('<span class="country"></span>').text(data.country) 255 ); 256 if (data.state) 257 location_breadcrumbs.push( 258 $('<span class="state"></span>').text(data.state) 259 ); 260 if (data.city) 261 location_breadcrumbs.push($('<span class="city"></span>').text(data.city)); 262 var location = $('<div class="location"></div>').append(data.headline); 263 264 // Rating 265 var rating = $('<div class="rating"></div>'); 266 if (data.review_average) drawListingStars(rating, data.review_average); 267 268 // Avatar 269 var avatar = $( 270 '<a href="/trips/' + 271 data.id + 272 '/"><img class="avatar" src="' + 273 data.user_details.photo_url + 274 '" /></a>' 275 ); 276 var badge = $('<div class="badge"></div>').append(avatar); 277 278 // User info 279 var user_rating_name = $('<div class="info"></div>').append( 280 rating, 281 $('<h5 class="name"></h5>').text(data.user_details.first_name) 282 ); 283 if (data.user_details.is_super_owner) 284 user_rating_name.append( 285 $( 286 '<span class="super-owner">Super Owner <img src="/static/img/[email protected]" /></span>' 287 ) 288 ); 289 290 var user_info = $('<div class="user"></div>').append(badge, user_rating_name); 291 292 // Price 293 var price = $('<div class="price-detail"></div>').append( 294 $('<span class="currency"></span>').text(data.search_price_nested.currency), 295 $('<span class="amount"></span>').text( 296 data.search_price_nested.formatted.replace( 297 data.search_price_nested.currency, 298 "" 299 ) 300 ), 301 $('<span class="label"></span>').text(data.search_price_nested.label) 302 ); 303 var price_info = $('<div class="price">').append( 304 $('<span class="from">From</span>'), 305 price 306 ); 307 308 // Combine user info + price 309 var info_wrap = $('<div class="details"></div>').append( 310 user_info, 311 price_info 312 ); 313 314 // Photos 315 var photo_list = []; 316 $.each( 317 data.photos.slice(0, photo_list.length > 3 ? photo_list.length : 3), 318 function (i, photo) { 319 photo_list.push( 320 $( 321 '<div class="photo"><a target="_blank" href="/trips/' + 322 data.id + 323 '/"><img src="' + 324 photo.url + 325 '" alt="' + 326 data.headline + 327 '"/></a></div>' 328 ) 329 ); 330 } 331 ); 332 var photos = $('<div class="photos"></div>').append(photo_list); 333 334 // Combine elements 335 $(el).append(photos, location, headline, info_wrap); 336} 337 338function createInitialLandingPage({location, referrer}) { 339 const utmParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_content', 'utm_term']; 340 const urlParams = new URLSearchParams(location.search); 341 const hrefWithoutSearch = location.href.split('?')[0]; 342 const gclid = urlParams.get('gclid') || undefined; 343 344 const utmValues = {}; 345 utmParams.forEach((param) => { 346 const value = urlParams.get(param); 347 if (value) { 348 utmValues[param] = value; 349 } 350 }); 351 352 return { 353 url: hrefWithoutSearch, 354 referrer, 355 gclid, 356 utmValues, 357 }; 358}
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.