1function combo_load_cell(element, display_function) { 2 window.console && console.warn('combo_load_cell is deprecated, use combo_cell_loader instead'); 3 combo_cell_loader({"element": element, "display_function": display_function}); 4} 5 6function combo_cell_url({base_url=null, element=null, dismiss_location_search=false} = {}) { 7 const elem = element.nodeType ? element : element[0]; 8 let current_url = new URL(window.location.href); 9 let url = base_url || elem.dataset.ajaxCellUrl; 10 11 // we need scheme://domain to use URL() 12 url = url[0] == '/' ? current_url.origin + url : url; 13 url = new URL(url); 14 15 // parameters to skip 16 const matches = ['cwcs', 'offset']; 17 if (elem.id) { 18 matches.push(elem.id); 19 } 20 const matcher = new RegExp('^(' + matches.join('|') + ')'); 21 22 // copy current URL parameters to ajax URL 23 current_url.searchParams.forEach((value, key) => { 24 if (matcher.exec(key) && dismiss_location_search) { 25 return; 26 } 27 url.searchParams.append(key, value) 28 }); 29 30 url = url.toString(); 31 url = url.includes('?') ? url + '&' : url + '?'; 32 const extra_url_params = elem.dataset.extraUrlParams || ''; 33 url = extra_url_params ? `${url}${extra_url_params}&` : url; 34 const extra_context = elem.dataset.extraContext; 35 url = extra_context ? `${url}ctx=${extra_context}` : url; 36 return url; 37} 38 39function combo_cell_loader({element=null, display_function=null, dismiss_location_search=false, tries=0} = {}) { 40 const elem = element.nodeType ? element : element[0]; 41 // clear existing timeout if any 42 clearTimeout(elem.timeout); 43 // abort previous request if one exists 44 if (elem.xhr !== undefined) { 45 elem.xhr.abort(); 46 } 47 // abort after 10 tries 48 if (tries > 10) { 49 return; 50 } 51 let url = combo_cell_url({"element": elem, "dismiss_location_search": dismiss_location_search}) 52 var $elem = $(element); 53 var display_function = display_function || function($element, data) { 54 $element.find('> div').html(data); 55 } 56 $.support.cors = true; /* IE9 */ 57 elem.xhr = $.ajax({url: url, 58 xhrFields: { withCredentials: true }, 59 async: true, 60 dataType: 'html', 61 crossDomain: true, 62 success: function(data, text_status, xhr) { 63 if (data == 'retry') { 64 let timeout = Math.min(30 * 1000, 1000 * Math.pow(2, tries)); 65 elem.timeout = setTimeout( 66 function() { 67 combo_cell_loader({"element": elem, tries: tries + 1}); 68 }, 69 timeout); 70 return; 71 } 72 var page_title = xhr.getResponseHeader('X-Page-Title'); 73 if (page_title) { 74 page_title = JSON.parse(page_title) 75 if (document.original_title === undefined) { 76 document.original_title = document.title 77 } 78 document.title = page_title + ' | ' + document.original_title; 79 } 80 $elem.addClass('ajax-loaded'); 81 $elem.find('> div').nextAll().remove(); 82 if (data == '') { 83 $elem.find('> div').remove(); 84 } else { 85 display_function($elem, data); 86 } 87 if (! $elem.find('> div').children().length) { 88 $elem.addClass('empty-cell'); 89 } else { 90 $elem.removeClass('empty-cell') 91 } 92 // Scroll to currently selected anchor 93 if (window.location.hash) { 94 var $anchor_element = $(window.location.hash); 95 if ($anchor_element.length) { 96 $('html').scrollTop($anchor_element.offset().top); 97 } 98 } 99 $(document).trigger('combo:cell-loaded', $elem); 100 }, 101 error: function(error) { 102 var msg = $elem.data('ajax-cell-error-message'); 103 if (!msg) msg = 'Unknown error (code: ' + error.status + ')'; 104 $elem 105 .removeClass('empty-cell') 106 .find('.loading') 107 .addClass('error-loading') 108 .html('<span class="loading-message">' + msg + '</span>'); 109 window.console && console.log(':(', error); 110 } 111 }); 112} 113 114function combo_modify_query_string(name, value) { 115 var search = window.location.search.substring(1); 116 var parts = search.split('&'); 117 var newparts = []; 118 var modified = 0; 119 value = encodeURIComponent(value); 120 for (var i = 0; i < parts.length; i++) { 121 if (! parts[i]) { 122 continue; 123 } 124 var pair = parts[i].split('='); 125 if (pair[0] == name) { 126 if (value) { 127 newparts.push(name + '=' + value); 128 } 129 modified = 1; 130 } else { 131 newparts.push(parts[i]); 132 } 133 } 134 if (! modified && value) { 135 newparts.push(name + '=' + value); 136 } 137 if (newparts) { 138 search = '?' + newparts.join('&'); 139 } else { 140 search = ''; 141 } 142 return search; 143} 144 145/* Launch callbacks when scroll move above and below a limit 146 * new ComboScrollY({ 147 * limit: int, 148 * below: callback function, 149 * above: callback function 150 * }) 151 */ 152function ComboScrollY(options) { 153 this.defaults = { 154 limit: 0 155 }; 156 this.options = options; 157 this.init(); 158}; 159ComboScrollY.prototype.init = function(){ 160 this.options = $.extend({}, this.defaults, this.options); 161 this.callbacks(); 162 window.addEventListener('scroll', this.callbacks.bind(this)); 163}; 164ComboScrollY.prototype.position = function(){ 165 return (window.pageYOffset <= this.options.limit) ? "above" : "below"; 166}; 167ComboScrollY.prototype.update = function(){ 168 return (this.position() === this.last_callback_position) ? false : true; 169}; 170ComboScrollY.prototype.callbacks = function() { 171 if (this.update()) { 172 if (this.position() === "below") { 173 this.options.below(); 174 this.last_callback_position = "below"; 175 } else { 176 this.options.above(); 177 this.last_callback_position = "above"; 178 } 179 } 180}; 181 182/* Make table widget responsive 183 * new Combo_Responsive_table_widget(table) 184 */ 185const Combo_Responsive_table_widget = function (table) { 186 'use strict'; 187 this.table = table; 188 this.col_headers = table.querySelectorAll('thead th, tr th'); 189 this.col_headers_text = []; 190 this.body_rows = table.querySelectorAll('tbody tr'); 191 this.init(); 192}; 193Combo_Responsive_table_widget.prototype.storeHeaders = function () { 194 'use strict'; 195 let _self = this; 196 $(this.col_headers).each(function (i, header) { 197 _self.col_headers_text.push(header.innerText); 198 }); 199 $(this.body_rows).each(function (i, tr) { 200 $(tr.querySelectorAll('td')).each(function (i, td) { 201 td.dataset.colHeader = _self.col_headers_text[i]; 202 }); 203 }); 204}; 205Combo_Responsive_table_widget.prototype.init = function () { 206 'use strict'; 207 this.table.classList.add('responsive-tableWidget'); 208 this.storeHeaders(); 209}; 210 211$(function() { 212 213 function pagination_update_page(items, max_page_index, step, paginate_by, $pagination, focus_first_item) { 214 var page_index = $pagination.data('page_index') + step; 215 if (page_index == 0) { 216 $pagination.find('.cell-items-pagination-prev').prop('disabled', true); 217 } else { 218 $pagination.find('.cell-items-pagination-prev').prop('disabled', null); 219 } 220 if (page_index == max_page_index - 1) { 221 $pagination.find('.cell-items-pagination-next').prop('disabled', true); 222 } else { 223 $pagination.find('.cell-items-pagination-next').prop('disabled', null); 224 } 225 start_item = paginate_by * page_index; 226 items.hide(); 227 items.slice(start_item, start_item + paginate_by).show(); 228 $pagination.data('page_index', page_index); 229 if (focus_first_item) { 230 $pagination.parent().focus(); 231 } 232 }; 233 234 function paginate($pagination, items, must_focus) { 235 $pagination.data('page_index', 0); 236 var paginate_by = parseInt($pagination.data('paginate-by')); 237 var max_page_index = Math.ceil(items.length / paginate_by); 238 if (items.length <= paginate_by) { 239 // hide pagination 240 $pagination.prop('hidden', true); 241 return; 242 } 243 244 function update_page(step, focus_first_item) { 245 if (! must_focus) { 246 focus_first_item = false;
247 } 248 pagination_update_page(items, max_page_index, step, paginate_by, $pagination, focus_first_item); 249 } 250 251 $pagination.find('.cell-items-pagination-prev').off("click"); 252 $pagination.find('.cell-items-pagination-next').off("click"); 253 $pagination.find('.cell-items-pagination-prev').click(function() { update_page(-1, true); }); 254 $pagination.find('.cell-items-pagination-next').click(function() { update_page(1, true); }); 255 update_page(0, false); 256 $pagination.prop('hidden', null); 257 }; 258 259 $('.cell-items-pagination').each(function(idx, elem) { 260 var $cells = $(elem).parents('.combo-cell'); 261 if ($cells.length) { 262 $(document).trigger('combo:cell-loaded', $cells.first()); 263 } 264 }); 265 266 $('[data-ajax-cell-refresh]').each(function(idx, elem) { 267 var $elem = $(elem); 268 function refresh() { 269 combo_cell_loader({"element": $elem}); 270 } 271 $elem.timeout_id = setInterval(refresh, $elem.data('ajax-cell-refresh')*1000); 272 }); 273 $(".combo-cell:not('.card') [data-ajax-cell-must-load]").each(function(idx, elem) { 274 combo_cell_loader({"element": $(elem).parents('.combo-cell')[0]}); 275 }); 276 $('div.combo-cell > div').each(function(idx, elem) { 277 if (! $('[data-ajax-cell-must-load]', $(elem)).length && ! $(elem).children().length) { 278 $(elem).parent().addClass('empty-cell'); 279 } 280 }); 281 282 /* utility functions and events, for themes */ 283 $('.togglable').on('click', function() { 284 $(this).toggleClass('toggled'); 285 }); 286 287 $(document).on('click keypress', '.add-more-items--button', function(e) { 288 if (e.type === 'keypress' && !(e.key === ' ' || e.key === 'Enter')) 289 return; 290 291 e.preventDefault(); 292 $(this).attr('aria-expanded', 'true'); 293 $(this).parent('.add-more-items').hide(); 294 $('#' + $(this).attr('aria-controls')).show().focus(); 295 }); 296 297 298 var menu_page_ids = $.makeArray($('[data-menu-page-id]').map(function() { return $(this).data('menu-page-id'); })); 299 if (menu_page_ids.length && $('body').data('check-badges') === true) { 300 $.ajax({url: $('body').data('api-root') + 'menu-badges/', 301 xhrFields: { withCredentials: true }, 302 async: true, 303 dataType: 'json', 304 data: {'page': menu_page_ids}, 305 crossDomain: true, 306 success: function(data) { 307 $(document).trigger('combo:menu-badges-loaded', data); 308 }}); 309 } 310 $(document).on('combo:menu-badges-loaded', function(ctx, data) { 311 for (var page_id in data) { 312 var badge = data[page_id]; 313 if (badge.badge) { 314 $('[data-menu-page-id=' + page_id + '] > a > span').append(' <span class="badge">' + badge.badge + '</span>'); 315 } 316 if (badge.klass) { 317 $('[data-menu-page-id=' + page_id + ']').addClass(badge.klass); 318 } 319 } 320 }); 321 $('.selfdeclaredinvoicepayment form').on('combo:load-invoice', window.displayPopup); 322 $('.selfdeclaredinvoicepayment form').on('submit', function(event) { 323 var url = $(this).attr('action'); 324 var data = $(this).serialize(); 325 var $form = $(this); 326 $.ajax({url: url + '?ajax=on', 327 xhrFields: { withCredentials: true }, 328 data: data, 329 async: true, 330 dataType: 'json', 331 success: function(data) { 332 if (data.msg) { 333 var err_msg = $('<p></p>'); 334 err_msg.text(data.msg); 335 $(err_msg).dialog({ 336 dialogClass: 'alert', 337 modal: true, 338 width: 'auto', 339 buttons: { 340 'Ã': function() { 341 $(this).dialog('destroy'); 342 } 343 }, 344 }); 345 return; 346 } 347 $form.data('url', data.url); 348 $form.trigger('combo:load-invoice', event); 349 }, 350 error: function(error) { 351 window.console && console.log(':(', error); 352 } 353 }); 354 return false; 355 }); 356 357 function set_booking_calendar_sensitivity(table) { 358 if ($(table).find('input:checked').length == 0) { 359 /* no checked box, enable them all */ 360 $(table).find('input').prop('disabled', false); 361 return; 362 } 363 364 /* disable every thing */
365 var column_index = $(table).find('input:checked').parents('td').index(); 366 $(table).find('td').removeClass('active-column').removeClass('clickable'); 367 $(table).find('input').prop('disabled', true); 368 369 /* enable checkboxes from the active column */ 370 $(table).find('td:nth-child(' + (column_index+1) + ') input').prop('disabled', false); 371 /* mark active column */ 372 $(table).find('td:nth-child(' + (column_index+1) + ')').addClass('active-column'); 373 374 /* enable contiguous checkboxes; this is done by adding a clickable class 375 * to the approriate checkboxes, as all of them need to be kept as enabled 376 * HTML-wise to be transmitted on POST. 377 */ 378 var checkboxes = $(table).find('td:nth-child(' + (column_index+1) + ') input:checked'); 379 380 /* enable the preceding one */ 381 $(checkboxes[0]).parents('tr').prev().find('td:nth-child(' + (column_index+1) + ')').addClass('clickable'); 382 /* enable first one, so it can be unchecked */ 383 $(checkboxes[0]).parents('td').addClass('clickable'); 384 /* enable last one, so it can be unchecked */ 385 $(checkboxes[checkboxes.length-1]).parents('td').addClass('clickable'); 386 /* enable the following one */ 387 $(checkboxes[checkboxes.length-1]).parents('tr').next().find('td:nth-child(' + (column_index+1) + ')').addClass('clickable'); 388 } 389 390 const foldableOptions = { 391 titleClass: 'cell--title', 392 pictureClass: 'cell--picture', 393 } 394 if ("gadjo_js" in window) { 395 gadjo_js.Foldable.initFoldableQuery('.cell.foldable', foldableOptions) 396 $(document).on('combo:cell-loaded', (_, cell) => { 397 if ('gadjoFoldable' in cell) { 398 cell.gadjoFoldable.prepareFoldable(cell) 399 } else if (cell.classList.contains('foldable')) { 400 gadjo_js.Foldable.initFoldableQuery(cell, foldableOptions) 401 } 402 }) 403 } 404 405 /* add a scrolled class to body once the user scrolled the page a bit */ 406 var body_is_scrolled = new ComboScrollY({ 407 above: function(){ 408 $('body').removeClass('scrolled'); 409 }, 410 below: function(){ 411 $('body').addClass('scrolled'); 412 } 413 }); 414 415 $('body').on('click', 'a.calchunk', function(event){ 416 event.preventDefault(); 417 var $elem = $(this); 418 var url = $elem.data('content-url'); 419 $.ajax({ 420 url: url, 421 async: true, 422 dataType: 'html', 423 crossDomain: true, 424 success: function(data){ 425 $elem.closest('div.calcontent').html(data); 426 }, 427 error: function(error){ 428 console.log(':(', error); 429 } 430 }); 431 }); 432 433 $('.bookingcalendar table').each(function(idx, elem) { set_booking_calendar_sensitivity(elem); }); 434 435 $('body').on('change', '.bookingcalendar input', function() { 436 set_booking_calendar_sensitivity($(this).parents('table')); 437 }); 438 439 $(document).on('focusin', 'input:not([type=checkbox]):not([type=radio]), textarea', function() { 440 $('body').addClass('focus-in'); 441 }) 442 $(document).on('focusout', 'input:not([type=checkbox]):not([type=radio]), textarea', function() { 443 $('body').removeClass('focus-in'); 444 }) 445 446 /* notifications */ 447 $('div.cell').delegate('li.combo-notification', 'click', function() { 448 var target_url = $(this).find('a').attr('href'); 449 if ($(this).hasClass('combo-notification-acked')) { 450 if (target_url != '#') { 451 window.location.href = target_url; 452 } 453 } else { 454 var ack_url = $('body').data('api-root') + 'notification/ack/' + $(this).data('combo-notification-id'); 455 $.ajax({ 456 url: ack_url, 457 success: function(html) { 458 $(this).addClass('combo-notification-acked'); 459 if (target_url != '#') { 460 window.location.href = target_url; 461 } 462 } 463 }); 464 } 465 return false; 466 }); 467 $(document).on('combo:cell-loaded', function(ev, cell) { 468 var $pagination = $(cell).find('.cell-items-pagination'); 469 if ($pagination.length == 0) return; 470 // Get all <li> inside the same div as us, ignoring whether they are part of 471 // different <ul> 472 var wrapper = $pagination.parent(); 473 wrapper.attr('tabindex', -1) 474 var items = $pagination.parent().find('.links-list li, tbody tr'); 475 paginate($pagination, items, true); 476 }); 477 // accessibililty enhancements: 478 // support for hiding some elements (such as submenus) 479 // when the escape key is pressed 480 $(document).keydown(function(e) { 481 if (e.key === "Escape") { 482 var $elt = $(document.activeElement); 483 if($elt.parent('.hide-on-escape')) { 484 $elt.trigger('blur'); 485 } 486 } 487 }); 488 // and ensure the elements can be viewed again 489 // on subsequent hover/focus 490 function reset_hidden_elements(event) { 491 var root_element = $(event.target).closest('.contains-hidden-elements') 492 $(root_element).find('.hide-on-escape').css({display: ''}) 493 } 494 $('.contains-hidden-elements').mouseenter(reset_hidden_elements, null) 495 $('.contains-hidden-elements').focusin(reset_hidden_elements) 496
497 $(document).on('combo:cell-loaded', function(e, cell) { 498 if (typeof multiSelectWidget !== 'undefined') { 499 multiSelectWidget.init(cell); 500 } 501 }); 502 503 function init_select2() { 504 $('select[data-combo-autocomplete]').each(function(idx, elem) { 505 $(elem).select2() 506 }); 507 } 508 init_select2(); 509 $(document).on('combo:cell-loaded', init_select2); 510 511 $(document).on('combo:cell-loaded', function(ev, cell) { 512 $(cell).find('.combo-cell:not(".pk-table-no-responsive") table:not(".pk-table-no-responsive")').has('th').each(function(i, table) { 513 new Combo_Responsive_table_widget(table); 514 }); 515 }); 516});
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.