1$.ajaxSetup({cache: false}); 2 3let pubUpdateInterval = null; 4 5 6function searchVessels(btn, subj, params) 7{ 8 var inp = $(btn).prev(); 9 var inp_offset = inp.offset(); 10 var cars_list = $('#cars_list'); 11 12 cars_list.css('left', inp_offset.left + 'px'); 13 cars_list.css('top', (inp_offset.top + inp.outerHeight() + 1) + 'px'); 14 15 cars_list.html('<div style="padding:4px 7px 2px"><img src="/img/loader_wb.gif" style="position:relative; top:-2px; width:16px; height:16px"> ' + _text['IX_WAIT'] + '</div>').show(); 16 17 $.getJSON('/api.php?action=index-qsearch', params, function(res) 18 { 19 if (res && res.length > 0) 20 { 21 var i, html = '<table class="wlist">\n'; 22 html += '<thead><tr><th>' + _text['NUMSIGN'] + '</th>'; 23 if (subj != 'NUMSIGN') html += '<th class="c">' + _text[subj] + '</th>'; 24 html += '<th>' + _text['SHORT_M'] + '</th><th class="r">' + _text['SHORT_B'] + '</th><th>' + _text['SHORT_C'] + '</th></tr></thead>\n'; 25 html += '<tbody>\n'; 26 27 for (i in res) 28 { 29 html += '<tr class="s' + (parseInt(res[i].state) + 10) + '" state="' + res[i].state + '" style="cursor:pointer">\n'; 30 html += '<td class="d" style="padding:5px 11px 5px 7px"><a href="/vessel/' + res[i].vid + '/" target="_blank">' + res[i].num + '</a></td>\n'; 31 if (subj != 'NUMSIGN') html += '<td class="cs" style="color:#000">' + res[i].subj + '</td>\n'; 32 html += '<td class="ds" style="color:#000">' + res[i].mname + '</td>\n'; 33 html += '<td class="rs" style="color:#000">' + res[i].built + '</td>\n'; 34 html += '<td class="ds" style="color:#000">' + res[i].cname + '</td>\n'; 35 html += '</tr>\n'; 36 } 37 38 html += '</tbody>\n'; 39 html += '</table>\n'; 40 41 cars_list.html(html); 42 43 var left = cars_list.offset().left; 44 var right = left + cars_list.outerWidth(); 45 var diff = $(window).width() - right; 46 47 if (diff < 0) cars_list.css('left', Math.max(left + diff, 0) + 'px'); 48 } 49 else cars_list.html('<div style="padding:5px 7px">' + _text['IX_NOTHING'] + '.</div>'); 50 }) 51 .fail((jx) => alert(jx.responseText)); 52 53 return false; 54} 55 56 57$(document).ready(function() 58{ 59 setTimeout(() => 60 { 61 initPhotoBlocks(); 62 63 $('#loadmore').on('click', loadPubPhotos); 64 65 if ($('#random-photos').length) 66 { 67 $('#newrand').on('click', loadRandomPhotos).click(); 68 pubUpdateInterval = setInterval(updatePubPhotos, 60000); 69 } 70 }, 500); 71 72 73 let exact = $('#exact').on('click', () => setCookie('exact', exact.prop('checked') ? 1 : 0)); 74 75 $('#src_num button').on('click', function() { searchVessels(this, 'NUMSIGN', { 'num': $('#num').val(), 'exact': exact.prop('checked') ? 1 : 0 })}); 76 $('#src_imo button').on('click', function() { searchVessels(this, 'IMO', { 'imo': $('#src_imo input').val() })}); 77 $('#src_mmsi button').on('click', function() { searchVessels(this, 'MMSI', { 'mmsi': $('#src_mmsi input').val() })}); 78 $('#src_rnum button').on('click', function() { searchVessels(this, 'SHORT_R', { 'rnum': $('#src_rnum input').val() })}); 79 $('#src_bnum button').on('click', function() { searchVessels(this, 'SHORT_N', { 'bnum': $('#src_bnum input').val() })}); 80 81 $('#qsearch input[type="text"]').keydown(function(e) 82 { 83 if (e.which == 13) 84 { 85 $(this).siblings('button').click(); 86 return false; 87 } 88 else 89 if (e.which == 27) 90 { 91 $('#cars_list').hide().html(''); 92 return false; 93 } 94 }); 95 96 97 $('#cars_list').on('mouseenter', 'tbody tr', function() 98 { 99 var state = parseInt($(this).attr('state')); 100 $(this).removeClass('s' + (parseInt(state) + 10)).addClass('s' + state); 101 $('a', this).css('color', 'red'); 102 }) 103 .on('mouseleave', 'tbody tr', function() 104 { 105 var state = parseInt($(this).attr('state')); 106 $(this).removeClass('s' + state).addClass('s' + (parseInt(state) + 10)); 107 $('a', this).css('color', ''); 108 }) 109 .on('click', 'tbody tr', function() { window.open($('a', this).attr('href')); }) 110 .on('click', 'tbody tr a', function(e) { e.preventDefault(); }); 111 112 113 $(document).on('click', function(e) 114 { 115 var target = $(e.target); 116 if (target.closest('#cars_list').length > 0 || target.is('button')) return; 117 118 $('#cars_list').hide().html(''); 119 120 e.stopPropagation(); 121 }); 122 123 124 $('#mname').modelSelector(null, { 125 selectCallback: function(item) { window.open('/projects/' + item.value + '/'); }, 126 clearField: true 127 }); 128 129 130 $('#loginbtn').on('click', function() 131 { 132 var username = $('#username').val().trim(); 133 var password = $('#password').val().trim(); 134 135 if (username != '' && username != '') 136 { 137 $('#loginbtn').prop('disabled', true).val(_text['IX_LOGGING']); 138 139 $.post('/api.php?action=check-login', { username: username, password: password, remember: $('#remember').is('checked') }, function(r) 140 { 141 if (r == 0) 142 $('#loginform').submit(); 143 else window.location.reload(); 144 }) 145 .fail((jx) => { if (jx.responseText != '') console.log(jx.responseText); }); 146 } 147 }); 148 149 150 $('#idx-more-search').on('click', function() 151 { 152 $(this).hide(); 153 $('#qsearch2, #qsearch3').show(); 154 return false;
155 }); 156}); 157 158 159 160function initPhotoBlocks() 161{ 162 let recent = $('#recent-photos'); 163 let mobile = recent.is('.mobile'); 164 165 let width = recent.width(); 166 167 let multiLineCount = Math.floor(width / (mobile ? 101 : 131)); 168 let singleLineCount = mobile ? 11 : multiLineCount; 169 recent.data('singleLineCount', singleLineCount); 170 171 let blockCount = multiLineCount * (multiLineCount > 5 ? 3 : 5); 172 recent.data('blockCount', blockCount); 173 174 let allCount = pdata.length; 175 if (blockCount > allCount) 176 { 177 blockCount = allCount; 178 if (allCount > multiLineCount) blockCount -= allCount % multiLineCount; 179 } 180 181 let i, pid = 0; 182 for (i = 0; i < blockCount; i++) 183 pid = addPhotoToBlock(recent, pdata[i]); 184 185 let firstpid = recent.data('firstpid') || 0; 186 recent.data('lastpid', pid).data('firstpid', Math.max(pdata[0][0] || pdata[0], firstpid)); 187} 188 189 190 191function getPhotoFileName(item) 192{ 193 let pid = item[0].toString().padStart(7, '0'); 194 195 let fn = '/photo/' + pid.substr(0, 2) + '/' + pid.substr(2, 2) + '/' + pid.substr(4, 2) + '/' + item[0] + '_s.jpg'; 196 if (item[2]) fn += '?' + item[2]; 197 198 return fn; 199} 200 201 202 203function addPhotoToBlock(block, arr, prepend) 204{ 205 if (typeof arr == 'number') arr = [arr, 0, 0]; 206 if (!udata) arr[1] = 0; 207 block[prepend ? 'prepend' : 'append']('<a href="/photo/' + arr[0] + '/" target="_blank" class="prw-animate" style="background-image:url(\'' + getPhotoFileName(arr) + '\')">' + (arr[1] ? '<div class="hdshade"><div class="com-icon">' + arr[1] + '</div></div>' : '') + '</a>'); 208 return arr[0]; 209} 210 211 212 213function loadRandomPhotos() 214{ 215 let recent = $('#recent-photos'); 216 let random = $('#random-photos'); 217 let newrand = $('#newrand'); 218 let loader = $('#newrand-loader'); 219
220 newrand.hide(); 221 loader.show(); 222 223 $.getJSON('/api.php', { action: 'load-random-photos', count: recent.data('singleLineCount'), showlimited: recent.data('limited') }, function(data) 224 { 225 random.html(''); 226 227 if (data) 228 { 229 for (let i = 0; i < data.length; i++) 230 addPhotoToBlock(random, data[i]); 231 } 232 else random.append('Load error'); 233 234 newrand.show(); 235 loader.hide(); 236 }) 237 .fail((jx) => { if (jx.responseText != '') console.log(jx.responseText); }); 238 239 return false; 240} 241 242 243 244function loadPubPhotos() 245{ 246 let block = $('#recent-photos'); 247 let lastpid = block.data('lastpid'); 248 let loadmore = $('#loadmore1'); 249 let hidden = $('a:hidden', block); 250 251 loadmore.prop('disabled', true).addClass('loader-button').val(' '); 252 253 $.getJSON('/api.php', { action: 'load-pub-photos', count: block.data('blockCount'), showlimited: block.data('limited'), lastpid: lastpid, hidden: hidden.length }, function(data) 254 { 255 if (data) 256 { 257 hidden.show(); 258 259 if (data.length) 260 { 261 let i, pid; 262 for (i = 0; i < data.length; i++) 263 pid = addPhotoToBlock(block, data[i]); 264 265 block.data('lastpid', pid); 266 } 267 } 268 else block.append('Load error'); 269 270 loadmore.prop('disabled', false).removeClass('loader-button').val(_text['IX_LOADMORE']); 271 }) 272 .fail((jx) => { if (jx.responseText != '') console.log(jx.responseText); }); 273} 274 275 276 277function updatePubPhotos() 278{ 279 let block = $('#recent-photos'); 280 let firstpid = block.data('firstpid'); 281 282 if (firstpid == 0) return; 283 284 $.getJSON('/api.php', { action: 'update-pub-photos', showlimited: block.data('limited'), firstpid: firstpid }, function(data) 285 { 286 if (data) 287 { 288 if (data.length) 289 { 290 let i, pid; 291 for (i = 0; i < data.length; i++) 292 { 293 $('a:visible', block).eq(-1).hide(); 294 pid = addPhotoToBlock(block, data[i], true); 295 } 296 297 block.data('firstpid', pid); 298 } 299 } 300 else clearInterval(pubUpdateInterval); 301 }) 302 .fail((jx) => { if (jx.responseText != '') console.log(jx.responseText); }); 303}
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.