PageSourceSearch

https://www.revierbuch.com/js/main.js?2.3.3

js revierbuch.com collected 2026-10-02 01:41:21 UTC 32,336 bytes, 1,037 lines download raw bytes

1// constans
2// if (window.location.host=='localhost:1234') {
3if (window.location.host==='localhost') {
4  MY_VERSION     = 'development';
5  // MY_PATH_WWW 	 = window.location.protocol+'//localhost:1234/SuperJagd2/';
6  // MY_PATH_WWW_S	 = 'https://localhost:1234/SuperJagd2/';
7  MY_PATH_WWW 	 = window.location.protocol+'//localhost/revierbuch/';
8  MY_PATH_WWW_S	 = 'https://localhost/revierbuch/';
9  MY_PATH_SJ     = 'https://localhost/superjagd2/';
10} else if (window.location.host==='revierbuch.test') {
11  MY_VERSION     = 'development';
12  // MY_PATH_WWW 	 = window.location.protocol+'//localhost:1234/SuperJagd2/';
13  // MY_PATH_WWW_S	 = 'https://localhost:1234/SuperJagd2/';
14  MY_PATH_WWW 	 = window.location.protocol+'//revierbuch.test/';
15  MY_PATH_WWW_S	 = 'https://revierbuch.test/';
16  MY_PATH_SJ     = 'https://localhost/superjagd2/';
17} else if (window.location.host==='test.revierbuch.com') {
18  MY_VERSION     = 'testing';
19  MY_PATH_WWW 	 = window.location.protocol+'//test.revierbuch.com/';
20  MY_PATH_WWW_S	 = 'https://test.revierbuch.com/';
21  MY_PATH_SJ     = 'https://test.superjagd.com/';
22} else {
23  MY_VERSION     = 'production';
24  MY_PATH_WWW 	 = window.location.protocol+'//www.revierbuch.com/';
25  MY_PATH_WWW_S	 = 'https://www.revierbuch.com/';
26  MY_PATH_SJ     = 'https://www.superjagd.com/';
27}
28modal_buttons = {
29  Abbrechen: function() {
30    $('#dialog').html('').dialog('destroy');
31  }
32};
33MY_MAP_BORDER_OPTIONS = { fill: false, dashArray:'5, 5',color: 'MidnightBlue', opacity: 1, weight: 3};
34MY_MAP_BORDER_OPTIONS2 = { fill: false, dashArray:'4, 4',color: 'coral', opacity: 1, weight: 2};
35MY_MAP_BORDER_OPTIONS3 = { fill: false,color: 'tomato', opacity: 1, weight: 2};
36MY_MAP_BORDER_OPTIONS4 = { fill: false, dashArray:'4, 4',color: 'coral', opacity: 1, weight: 2};
37CBLUE = 'lightskyblue';
38CRED  = 'tomato';
39CGREEN = 'LimeGreen';
40CGRAY = 'gray';
41CPRIVATE = '#ff99ff';
42CSILVER = 'silver';
43GLEGEND = [
44  {className:'no-print', name:'<span class="ui-icon ui-icon-refresh" style="display: inline-block; vertical-align:text-top;"></span> - Liste neu laden (letzte Zeile links) ',autowidth:true, clear:true},
45  {className:'no-print', name:'<span class="ui-icon ui-icon-newwin" style="display: inline-block; vertical-align:text-top;"></span> - Spalten ein- und ausblenden (CTRL Taste gedrückt halten) ',autowidth:true}
46];
47MY_STORIES_COLORS = ['SandyBrown','#c58ed2','#88c4ff','tomato','LimeGreen','#bbb','Turquoise'];
48MY_PLACES_COLORS = [MY_STORIES_COLORS[2],MY_STORIES_COLORS[1],MY_STORIES_COLORS[5],CGREEN,CRED];
49MY_PLACES_COLORS_B = ['blue','darkviolet','dimgrey','darkgreen','darkred']; // for borders
50
51// detect touch devices
52IS_TOUCH = 'ontouchstart' in document.documentElement;
53
54$(function(){
55
56
57  // preload header img
58  var img=new Image();
59  img.src=MY_PATH_WWW+'images/layout/header_logo_over.jpg';
60
61  // reload
62  $(document).on('click','.reload_link',function(e){
63    e.preventDefault();
64    location.href = $(this).attr('href');
65    location.reload();
66  });
67
68  // empty states
69  if($('#empty_state').data('show')==='Y') {
70    $('#empty_state').show();
71  }
72  $('#empty_state').click(function(){
73    $(this).hide();
74  });
75  $('#show_es_tips').click(function(){
76    $('#empty_state').show();
77  });
78
79  // --- HEADER ---
80  // user
81  $('#h_navi_top a:first-child').click(function(e){
82    e.preventDefault();
83    location.href = $(this).attr('href');
84    if(ci_router('class')==='jaeger') {
85      location.reload();
86    }
87  });
88
89  // info
90  $('header .info').click(function(){
91    $(this).hide();
92  });
93
94  // main navi
95  $('#h_navi_main li')
96    .on('mouseover',function () {
97      $(this).find('.h_navi_main_2').show();
98    })
99    .mouseout(function () {
100      $(this).find('.h_navi_main_2').hide();
101    });
102  $('#h_navi_main li a span') // touch devices - touch arrow
103    .on('touchstart',function(e){
104      var $sel = $(this).parent().parent().find('.h_navi_main_2'); // select navi div
105      if(!$sel.is(':visible')) { // on 1st touch show menu, then go to section main page
106        e.preventDefault();
107      }
108      $('.h_navi_main_2').hide(); // hide all
109    $sel.show(); // show actual
110  })
111
112  // footer
113  $('.feedback').click(function(e){
114    e.preventDefault();
115    var title = 'Fehler, Fragen, Wünsche - der RevierBuch Support';
116    var file_data;
117    var buttons = $.extend({}, modal_buttons);
118    // action
119    buttons['Senden'] = function() {
120      var form_data = new FormData();
121      form_data.append("file", file_data);
122      form_data.append("title", $('[name=feedback_title]').val());
123      form_data.append("text", $('[name=feedback_text]').val());
124      form_data.append("file", window.location.href);
125      $('#dialog')
126        .html('').dialog('destroy')
127        .attr('title',title)
128        .html('<div class="color_warning">Ihr Anfrage wird versendet...</div>').dialog();
129      $.ajax({
130        url: MY_PATH_WWW+'feedback',
131        dataType: 'script',
132        cache: false,
133        contentType: false,
134        processData: false,
135        data: form_data,
136        type: 'post',
137        success: function(){
138          $('#dialog')
139            .html('').dialog('destroy')
140            .attr('title',title)
141            .html('<div class="color_ok">Vielen Dank, Ihre Anfrage wurde versendet!</div>').dialog();
142        }
143      });
144    };
145    // init
146    $('#dialog')
147      .attr('title',title)
148      .html('<div class="form" style="margin-top: 1em">\n\
149          <span class="color_warning">\n\
150            <b>Haben Sie eine Frage, einen Fehler gefunden oder einen Wunsch?</b><br>\n\
151            <br>\n\
152            Machen Sie bitte ein Bildschirmfoto (siehe weiter) und schreiben Sie ein paar Erklärungen zum Thema, damit wir Ihr Anliegen besser verstehen können.<br>\n\
153          </span>\n\
154          <form id="feedback_form" style="margin-top: 1em">\n\
155            <div class="element" id="feedback_screenshot">\
156            <ol class="not-tight" style="padding-left: 1em;">\
157            <li>Schließen Sie diesen Dialog (<i>ESC</i> Taste, <i>Abbrechen</i> oder <span style="display: inline-block; vertical-align: top" class="ui-button-icon-primary ui-icon ui-icon-closethick"></span>).</li>\
158            <li>Gegen Sie zur der Stelle wo Ihr Anliegen am besten zu sehen ist und drücken Sie die <strong>Print Screen</strong> Taste (<i>Druck</i> bzw. <i>PrtScn</i>) auf der Tastatur.</li>\
159            <li>Öffnen Sie diesen Dialog wieder (<i>Fehler/Frage</i>).</li>\
160            <li>Drücken Sie auf <strong>STRG + V</strong>.</li>\
161            <li>Schreiben Sie kürz über Ihr Anliegen (<i>Titel</i> und <i>Text</i>).</li>\
162            </ol>\
163            </div>\n\
164            <div class="element"><input type="text" name="feedback_title" style="width:96%" placeholder="Titel"></input></div>\n\
165            <div class="element"><textarea name="feedback_text" style="width:96%" placeholder="Text"></textarea></div>\n\
166            <div class="element"><input type="file" id="feedback_file" name="feedback_file" style="width:calc(96% + 6px)" placeholder="Anhang"></input></div>\n\
167          </form>\n\
168          Wir werden uns in Kürze im Ihrer Anfrage befassen!\n\
169        </div>\n\
170        ')
171      .dialog({
172        modal: true,
173        width: 500,
174        buttons: buttons,
175        open: function() {
176          $(document).on('paste','#dialog',function(e){
177            addEventListener("paste", ev => {
178              for(const item of ev.clipboardData.items) { /// Clipboard may contain multiple elements of different type -- text, image, etc
179                if(item.type.startsWith("image/")) { /// We are only interested in clipboard data that is an image
180                  $('#feedback_screenshot').html('<img src="'+URL.createObjectURL(item.getAsFile())+'" style="width: 96%">');
181                  var fileInput = document.getElementById("feedback_file");
182                  fileInput.files = ev.clipboardData.files;
183                  file_data = item.getAsFile();
184                  $('#feedback_file').hide();
185                }
186              }
187            });
188          })
189        }
190      });
191  });
192
193
194  // --- FORMS ---
195  // submit
196  set_form_submit();
197
198  // disabled
199  $(':disabled').addClass('disabled');
200
201  // buttons
202  $('.button-add').prepend('<span class="ui-icon ui-icon-circle-plus"></span>');
203  $('.button-export').prepend('<span class="ui-icon ui-icon-circle-arrow-s"></span>');
204
205  // checkboxes
206  $('input[type=checkbox] + span').click(function(){
207    $(this).prev().click();
208  });
209
210  // optional elements opacity
211  set_form_elements_opacity();
212
213  // --- RIGHTS ---
214  if(!$('[name=right_create_item]').val()) {
215    $('.button-add').remove();
216  }
217
218  // facebook login hash corrections
219  if(location.hash==='#_=_') {
220    history.replaceState(null, null, document.location.pathname);
221  }
222
223});
224
225// ------ FUNCTIONS -------
226/**
227 * Return URI Segment
228 *
229 * analog to Codeigniter's Router class
230 *
231 * @param {string} route_segment (class|method|pars)
232 * @returns {String/Array}
233 */
234function ci_router(route_segment) {
235
236  var segments = window.location.href.replace(MY_PATH_WWW,'').replace(window.location.hash,'').replace('#','').split('/');
237
238  switch (route_segment) {
239    case 'class':
240      return segments[0];
241    case 'method':
242      return segments[1];
243    case 'pars':
244      return segments.splice(3);
245  }
246}
247
248
249
250// --- FORMS ---
251/**
252 * Remove and Add Regions by Changing Country
253 *
254 * @param {string} country_selector name
255 * @param {string} region_selector name
256 */
257function change_regions_by_country(country_selector,region_selector) {
258
259  country_selector = (country_selector)?country_selector:'country_id';
260  region_selector = (region_selector)?region_selector:'countries_region_id';
261
262  var countries_regions = new Object();
263
264  $('[name='+region_selector+'] option').each(function(){
265    if($(this).val()) {
266      countries_regions[$(this).val()] = [$(this).text(),$(this).attr('selected')];
267      $(this).remove();
268    }
269  });
270
271  $('[name='+country_selector+']').change(function(){
272    var country_id = $(this).val();
273    $('[name='+region_selector+'] option').not('[value=""]').remove();
274    $.each(countries_regions,function(index,value){
275      var countries_region_country_id = index.substr(0,index.indexOf('-'));
276      var countries_region_region_id  = index.substr(index.indexOf('-')+1);
277      if(country_id===countries_region_country_id) {
278        $('[name='+region_selector+']').append('<option value="'+countries_region_region_id+'" '+(value[1]?value[1]:'')+'>'+value[0]+'</option>');
279      }
280    });
281    $('[name='+region_selector+']').change();
282  }).change();
283
284}
285
286/**
287 * Highlight Comment On Focus
288 *
289 * highlight field comment on focus and remove highlight on blur if not changed
290 *
291 * @param {string} field_name
292 */
293function highlight_comment_on_focus (field_name) {
294  var $this = $('[name='+field_name+']');
295  var $comm = $this.siblings('div.comm');
296  var value = $this.val();
297  $this
298  .focus(function(){
299    $comm.addClass('color_warning');
300  }).blur(function(){
301    if (value==$this.val()) $comm.removeClass('color_warning');
302  });
303}
304
305/**
306 * Highlight Error Fields
307 *
308 * highlight form fields with errors
309 */
310function highlight_error_fields () {
311  $('.element').each(function(){
312    var $errors = $(this).children('div.error');
313    if($errors.length==2) {
314      $errors.prev().prev().css('border-color','tomato');
315    } else
316    if($errors.length==1) {
317      $errors.prev().css('border-color','tomato');
318    }
319  });
320}
321
322/**
323 * Remove Table Rows If Any Cell Is Empty
324 *
325 * and set 2nd parent opacity to 1
326 *
327 * @param {text} selector
328 */
329function remove_table_rows_if_cell_empty(selector) {
330  $('#tab-ansicht table').find('tr').each(function(){
331    var $tr = $(this);
332    $tr.children().each(function(){
333      if($(this).html().trim()==='') {
334        $tr.remove();
335      };
336    });
337  });
338  $(selector).parent().parent().css('opacity','1');
339}
340
341/**
342 * Helper Function for set_datepicker_interval
343 *
344 * @param {string} field name of set field
345 */
346function set_datepicker_field_quarter(field) {
347  var val = $("[name="+field+"]").val();
348  if (val.substr(8,1)=='q') {
349    var year  = val.substr(0,4);
350    var month = val.substr(5,2);
351    var quarter = '';
352    switch(month){
353      case "01":
354      case "02":
355      case "03":
356        quarter = 1;
357        break;
358      case "04":
359      case "05":
360      case "06":
361        quarter = 2;
362        break;
363      case "07":
364      case "08":
365      case "09":
366        quarter = 3;
367        break;
368      case "10":
369      case "11":
370      case "12":
371        quarter = 4;
372        break;
373    }
374    var date = year+'-'+quarter;
375    $("[name="+field+"]").val(date);
376  }
377}
378
379/**
380 * Set Opacity According To Value And Focus
381 *
382 * 1 if focus or any value set
383 */
384function set_form_elements_opacity() {
385  $('.opt input, .opt textarea, .opt select').each(function(){
386    if(($(this).val()!=='' && $(this).val()!=='0' && $(this).val()!==null && $(this).attr('type')!=='checkbox') || ($(this).attr('type')==='checkbox' && $(this).prop('checked'))) {
387      $(this)
388        .parent().css('opacity','1')
389        .parent().css('opacity','1');
390    }
391  });
392  $('input, select, textarea')
393    .focus(function(){
394      $(this)
395        .parent().css('opacity','1')
396        .parent().css('opacity','1');
397    })
398    .blur(function(){
399      if($(this).val()==='') {
400        $(this)
401          .parent().css('opacity','')
402          .parent().css('opacity','');
403        }
404    });
405}
406
407/**
408 * Set Datepicker for Selecting Intervals
409 *
410 * @param {string} field name of set field
411 */
412
413/**
414 * Create Function for Loop in set_datepicker_interval()
415 *
416 * @param i
417 */
418function create_datepicker_months_func(i) {
419  return function() {
420    $(this).dialog( "close" );
421    $('#block-message-flash div').remove();
422    $field.datepicker('option','dateFormat','yy-mm-dd+'+i+"'Mo'").datepicker('show');
423  };
424}
425
426function set_datepicker_interval(field) {
427  $('[name='+field+']')
428    .datepicker({
429      showOn: 'none'
430    })
431    .change(function(){
432      set_datepicker_field_quarter(field);
433    });
434    $('[name='+field+']').click(function(){
435      var months = {};
436      for (var i=1;i<=12;i++) {
437        months[i] = create_datepicker_months_func(i);
438      }
439      $field = $(this);
440      // get type
441      var format;
442      $container = $('#block-message-flash');
443      $container.append('<div>Bitte wählen Sie die Art des Zeitraums und danach im Kalender einen Tag im gewünschten Zeitraum bzw. den ersten Tag des Zeiraums (Monate).</div>');
444      $container.find('div').dialog({
445        title: 'Zeitraum Filter',
446        resizable: false,
447        modal: true,
448        width: 420,
449        buttons: {
450          Tag: function() {
451            $(this).dialog( "close" );
452            $('#block-message-flash div').remove();
453            $field.datepicker('option','dateFormat','yy-mm-dd').datepicker('show');
454          },
455          Monat: function() {
456            format = 'yy-mm';
457            $(this).dialog( "close" );
458            $('#block-message-flash div').remove();
459            $field.datepicker('option','dateFormat','yy-mm').datepicker('show');
460          },
461          Monate: function () {
462            $(this).dialog( "close" );
463            $('#block-message-flash div').remove();
464            $container.append('<div>Bitte wählen Sie die Anzahl der Monate für den Zeitraum und im nächsten Schritt dann den ersten Tag des Zeitraums.</div>');
465            $container.find('div').dialog({
466              title: 'Zeitraum - Monate',
467              resizable: false,
468              modal: true,
469              width: 420,
470              buttons: months
471            });
472          },
473          Jahr: function() {
474            $(this).dialog( "close" );
475            $('#block-message-flash div').remove();
476            $field.datepicker('option','dateFormat','yy').datepicker('show');
477          },
478          Löschen: function() {
479            $field.val("").datepicker("hide").change();
480            eval(field+"	= '';");
481            $(this).dialog( "close" );
482            $('#block-message-flash div').remove();
483          }
484        }
485      });
486    });
487}
488
489/**
490 * Open Dialog and Close With Delay
491 *
492 * @param {string} title
493 * @param {string} text
494 * @param {object} buttons object (global variable buttons extension)
495 * @param {string} text_type S|W|E (success|warning=default|error)
496 */
497function set_dialog_modal(title,text,buttons,text_type = 'warning') {
498  $('#dialog').attr('title',title).html('<div class="color_'+text_type+'">'+text+'</div>').dialog({
499    modal: true,
500    buttons: buttons,
501    close: function() {
502      $('#dialog').html('').dialog('destroy');
503    }
504  });
505}
506
507/**
508 * Open Dialog and Close With Delay
509 *
510 * @param {string} title
511 * @param {string} text
512 * @param {int} time delay time in ms (or empty for 2000)
513 */
514function set_dialog_timeout(title,text,time=2000,reload=false) {
515  $('#dialog').attr('title',title).html(text).dialog({
516    width: 300,
517    close: function() {
518      $('#dialog').html('').dialog('destroy');
519    }
520  });
521  setTimeout(function(){
522    if(reload) {
523      location.reload();
524    } else {
525      $('#dialog').dialog('close');
526    }
527  },time);
528}
529
530/**
531 * Set Filter Variables
532 *
533 * @param {string} type return type
534 * @returns {String|Object}
535 */
536function set_filter_vars (type) {
537  var type = (type) ? type : 'object';
538  var filter = (type==='object') ? new Object() : '';
539  $('#mainContF :input').each(function(){
540    if($(this).hasClass('select2-search__field')) return true;
541    var name = $(this).attr('name');
542    var value =
543      $(this).parent().hasClass('hidden') // hide inactive filter
544        ?''
545        :$(this).val();
546    if($(this).attr('multiple')&&value) {
547      value = value.join(",");
548    }
549
550    if(type==='object') filter[name] = value;
551    else                filter += name+'='+value+'&';
552  });
553  return filter;
554}
555
556/**
557 * Set Overlay and Prevent Secondaty Sending
558 */
559function set_form_submit() {
560  $('#loading_overlay').hide();
561  $('form')
562    .data('submitted', false)
563    .on('submit',function(e){
564    var $form = $(this);
565    if ($form.data('submitted') === true) {
566      e.preventDefault();
567    } else {
568      $('#loading_overlay').show();
569      $form.data('submitted', true);
570    }
571  });
572}
573
574/**
575 * Set All Forms Not Submitted
576 *
577 * hide Overlay and remove disabled attribude
578 *
579 */
580function set_form_not_submitted() {
581  $('form').data('submitted', false);
582  $('form input[type=submit]').removeAttr('disabled').removeClass('disabled');
583  $('#loading_overlay').hide();
584}
585
586/**
587 * Set Title Desc for Filter
588 *
589 * @param {object} filter
590 */
591function set_title_desc (filter) {
592  var prefix = '';
593  var cont = '';
594  var title = '';
595  var desc = 'Filter: ';
596  $.each(filter,function(index, value){
597    if($('[name='+index+']').parent().hasClass('hidden') || $('[name='+index+']').attr('type')=='hidden') {
598      return true;
599    }
600    cont += value;
601    var $field = $('[name='+index+']');
602    if (value) {
603      // date
604      if(value.slice(-2)==='-q'||value.length===9) {
605        var month = value.slice(5,7);
606        var quarter = '';
607        switch(month){
608          case "01":
609          case "02":
610          case "03":
611            quarter = 1;
612            break;
613          case "04":
614          case "05":
615          case "06":
616            quarter = 2;
617            break;
618          case "07":
619          case "08":
620          case "09":
621            quarter = 3;
622            break;
623          case "10":
624          case "11":
625          case "12":
626            quarter = 4;
627            break;
628        }
629        value = value.slice(0,4)+'-'+quarter;
630      }
631      // accountings date type
632      if(index=='f_date_field') {
633        prefix = $field.find('option:selected').text()+' ';
634        return true; // skip iteration
635      }
636      if(index=='f_dat'||index=='f_yea') {
637        desc+=prefix;
638      }
639      // process
640      var name =  $field.parent().children('label').text();
641      var value = ($field.is('select')) ? $field.find('option:selected').text() : value;
642      if(index=='f_sec') {
643        var options = [];
644        $.each($field.find('option:selected'), function(){
645          options.push($(this).text());
646        });
647        value = options.join(', ');
648      }
649      desc += name + '&nbsp;<b>' + value + '</b>';
650      desc += value!=="Datum/Zeitraum:"? ' | ' : '';
651    }
652  });
653  if(desc==='Filter: ') {
654    desc = 'keine Filter  ';
655  }
656
657  // desc
658  desc = (desc) ? desc : 'keine Filter  ';
659  var descText = desc.slice(0,-2);
660  $('#filter-desc div').html(descText);
661}
662
663
664
665
666// --- MISC ---
667/**
668 * Reset Form's Value to Empty
669 *
670 * @param {object} $form
671 */
672function resetForm($form) {
673  $form.find(':input').not(':button, :submit, :reset').each(function () {
674    if(($(this).attr('name')!=='weight_limit_min' && $(this).val()!=='0') && ($(this).attr('name')!=='weight_limit_max'&&$(this).val()!=='∞')) {
675      $(this)
676        .attr('value', '')
677        .removeAttr('checked')
678        .removeAttr('selected');
679    }
680  });
681}
682
683// process link only after confirmation
684function process_link(link_class,confirmation) {
685  $('.'+link_class).click(function(event){
686    event.preventDefault();
687    var conf = confirm(confirmation);
688    if(conf) {
689      if($(this).attr('target')=='_blank') {
690        window.open($(this).attr('href'));
691      } else {
692        window.location.href = $(this).attr('href');
693      }
694    }
695  });
696}
697
698// get number from an element with id ending with a number (one digit numbers only)
699function getElementNumber($this) {
700  var id = $this.attr('id');
701  return  (id)?id.substring(id.length-1):0;
702}
703
704/**
705 * Format Table Column Aligns
706 *
707 * @param {string} table_selector
708 * @param {array} align_array e.g. ['L','L','R','C']
709 */
710function formatTableAligns(table_selector,align_array) {
711  $(table_selector+' tr').each(function(){
712    $(this).children('td, th').each(function(i){
713      var align;
714      if(align_array[i]!=='l'&&align_array[i]!=='L') {
715        switch(align_array[i]) {
716          case 'c':
717          case 'C':
718            align = 'align-center';
719            break;
720          case 'r':
721          case 'R':
722            align = 'align-right';
723            break;
724        }
725        $(this).addClass(align);
726      }
727    });
728  });
729}
730
731/**
732 * Format Table Rows by Column Value
733 *
734 * @param {string} table_selector
735 * @param {string} column title
736 * @param {array} format {value:'key'} e.g. {'Y'=>'green_class','N'=>'red_class'} | 'minus' as value if negative value
737 * @param {boolean} column_only
738 */
739function formatTableRows(table_selector,column,format,column_only) {
740  var col_index ;
741  // get column
742  $(table_selector).find('thead').find('th').each(function(i){
743    if ($(this).text()==column) {
744      col_index = i;
745    }
746  });
747  // apply class
748  $(table_selector+' tr').each(function(){
749    var tr = $(this);
750    $(this).children('td').each(function(i){
751      if(i===col_index) {
752        var td = $(this);
753        $.each(format,function(index, value){
754          if((td.text()===index) || (index=='minus'&&td.text().indexOf('-')===0)) {
755            if(column_only) {
756              td.addClass(value);
757              td.find('a').addClass(value);
758            } else {
759              tr.addClass(value);
760              tr.find('a').addClass(value);
761            }
762          }
763        });
764      }
765    });
766  });
767}
768
769// get month name
770function getMonth(month) {
771  var months = new Array("Januar", "Februar", "März", "April", "Mai", "Juni", "Juli", "August", "September", "Oktober", "November", "Dezember");
772  return months[month];
773}
774
775// get name of weekday
776function getWeekDayName(day,short) {
777  var days_short = new Array('So','Mo','Di','Mi','Do','Fr','Sa');
778  var days_full = new Array('Sonntag','Montag','Dienstag','Mittwoch','Donnerstag','Freitag','Samstag');
779
780  return (short) ? days_short[day] : days_full[day];
781}
782
783/**
784 * Get Current Date's MS Timestamp
785 *
786 * @param {string} format YMDT | YMD | YM | Y
787 * @returns {String}
788 */
789function getDateTime(format) {
790
791  if(!format) {
792    format = 'YMDT';
793  }
794
795  var today = new Date();
796  var ms = today.getMinutes();
797  var hh = today.getHours();
798  var dd = today.getDate();
799  var mm = today.getMonth()+1; //January is 0!
800  var yyyy = today.getFullYear();
801
802  if(dd<10) {
803      dd='0'+dd;
804  }
805  if(mm<10) {
806      mm='0'+mm;
807  }
808  if(hh<10) {
809      hh='0'+hh;
810  }
811  if(ms<10) {
812      ms='0'+ms;
813  }
814
815  switch(format) {
816    case 'YMDT':
817      return yyyy+'-'+mm+'-'+dd+' '+hh+':'+ms;
818      break;
819    case 'YMD':
820      return yyyy+'-'+mm+'-'+dd;
821      break;
822    case 'YM':
823      return yyyy+'-'+mm;
824      break;
825    case 'Y':
826      return yyyy;
827      break;
828  }
829}
830
831// get js date object from timestamp
832function getDateFromTS(ts) {
833  return new Date((ts+':00').replace(/-/g, "/"));
834}
835
836/**
837 * Set Events for Image Matrix Info Layer
838 */
839function setMatrixInfoLayer(grid) {
840
841  var offsetX = grid ? 15 : 15;
842  var offsetY = grid ? 15 : 15;
843
844  $(document)
845    .on('mouseover','#mainContM a.img-link',function(e){
846      $('#imgInfo').remove();
847      var $this = $(this);
848      var title = $this.data('title').replace(' - ','<br>');
849
850      var pos = $this.children('img').position();
851      $this.after('<div id="imgInfo">'
852        +'<div id="actions"><div id="delete" data-id="'+$this.data('id')+'" class="ui-icon ui-icon-circle-minus" ></div>'
853        +'<div id="mark"   data-id="'+$this.data('id')+'" data-st="'+$(this).children('img').hasClass('bm')+'" class="ui-icon ui-icon-star" ></div></div>'
854        +title+'</div>');
855      $('#imgInfo')
856        .css('left',pos.left+offsetX).css('top',pos.top-offsetY)
857        .show();
858    })
859    .on('mouseenter','#mainContM',function(e){
860      $('#imgInfo').remove();
861    })
862    .on('click','.delete',function(e){
863      e.preventDefault();
864    })
865    .on('click','#mainContM a.img-link',function(e){
866      e.preventDefault();
867      if(grid) {
868        open_detail($(this).attr('id'),grid);
869      } else {
870        location.href = MY_PATH_WWW+'wildkameras#id'+$(this).attr('id');
871      }
872    });
873}
874/**
875 * Set Colors for Śelect Option
876 *
877 * @param {string} name select name
878 * @param {type} options array of option value|color objects ({value:'A',color:'lightgreen'},{value:'L',color:'red'})
879 */
880function setSelectOptionsColor(name,options) {
881  $('[name='+name+']').change(function(){
882    var $this = $(this);
883    $.each(options,function(i,option){
884      $this.children('option[value="'+option.value+'"]').filter(':selected').parent().css('color',option.color);
885      $this.children('option[value="'+option.value+'"]').css('color',option.color);
886    });
887  }).change();
888}
889
890/**
891 * Replace special characters in Javascript
892 *
893 * @param {string} str
894 * @returns {string}
895 */
896function str2slug(str) {
897	var rep = '_';
898
899	// str = str.toLowerCase().replace(/\s+/g, rep) // replace whitespace
900
901	// remove accents, swap ñ for n, etc
902	var from = "¡¿ÀàÁáÂâÃãÅåǍǎĄąĂăÆæÇçĆćĈĉČčĎđĐďðÈèÉéÊêËëĚěĘęĜĝĢģĤĥÌìÍíÎîÏïĴĵĶķĹĺĻļŁłÑñŃńŇňÒòÓóÔôÕõŐőØøŔŕŘřẞŚśŜŝŞşŠšŤťŢţÞþÙùÚúÛûŰűŨũŲųŴŵÝýŸÿŶŷŹźŽžŻż";
903	var to   = "  aaaaaaaaaaaaaaaaaaccccccccdddddeeeeeeeeeeeegggghhiiiiiiiijjkkllllllnnnnnnoooooooooooorrrrsssssssssttttttuuuuuuuuuuuuwwyyyyyyzzzzzz";
904	for (var i=0, l=from.length ; i<l ; i++) {
905	    str = str.replace(
906                new RegExp(from.charAt(i), 'g'),
907                to.charAt(i)
908            );
909	}
910        // remove invalid chars
911	str = str.replace(new RegExp('[^äÄöÖßÜüa-zA-Z 0-9'+rep+']',"g"), '')
912        .replace(/-+/g, rep); // collapse dashes;
913
914	return str;
915}
916
917/**
918 * Show Hide Table Rows
919 *
920 * if more than "visible_cnt" by clicking ".link_right"
921 *
922 * @param {string} parent_selector
923 * @param {int} visible_cnt
924 */
925function showHideTableRows(parent_selector,visible_cnt) {
926  $(parent_selector).find('table tr').each(function(i){
927    if(i>(visible_cnt-1)) {
928      $(this).attr('data-hide','Y').hide();
929      var hidden_cnt = $(parent_selector).find('table tr[data-hide=Y]').length;
930      $(parent_selector).find('.cut_info').text('und '+hidden_cnt+' weitere Zeile'+(hidden_cnt>1?'n':''));
931    }
932  });
933  $(parent_selector).find('.link_right').click(function(e){
934    e.preventDefault();
935    $(parent_selector).find('table tr[data-hide=Y]').toggle();
936    $(parent_selector).find('.cut_info').toggle();
937    var sp = $(this).find('span');
938    sp.text(sp.text()=='alle'?'10':'alle');
939  });
940}
941
942// show description next to selector after change
943function showRotateDescription () {
944  $('[name=rotate]').change(function(){
945    $(this).next().remove();
946    var text;
947    switch($(this).val()) {
948      case '90':
949        text = 'Foto wird nach links gedreht';
950        break;
951      case '270':
952        text = 'Foto wird nach rechts gedreht';
953        break;
954      case '180':
955        text = 'Foto wird um 180° gedreht';
956        break;
957    }
958    if(text) {
959      $(this).after('<span>'+text+'</span>');
960    }
961  });
962}
963
964
965/**
966 * Truncate Text
967 *
968 * @param {String} text
969 * @param {Number} characters count
970 * @param {String} delimiter string (e.g. ' ', '/')
971 * @returns {String}
972 */
973function truncate_text(text,characters,delimiter) {
974  var delimiter = delimiter?delimiter:' ';
975  return text.length<=characters ? text : $.trim(text).substring(0, characters).split(delimiter).slice(0, -1).join(delimiter) + "...";
976}
977
978
979// --- MAPS ---
980/**
981 * Prepare Provider Layers
982 *
983 * @param {string} saved_name name of last user provider saved by cookie
984 * @return {{baseMaps: {}, providers: *[]}, currentIndex:int}
985 */
986function map_providers_prepare (saved_name) {
987  let providers = ['OpenTopoMap', 'Thunderforest.Outdoors', 'BasemapAT.grau', 'BasemapAT.orthofoto', 'Esri.WorldImagery'];
988  if(MY_COUNTRY!==1) {
989    providers = ['OpenTopoMap', 'Thunderforest.Outdoors', 'Esri.WorldImagery'];
990  }
991  const currentIndex = saved_name?providers.findIndex(el => saved_name === el ):(MY_COUNTRY===1?2:1);
992  var provider = [];
993  var baseMaps = {};
994  $.each(providers,function(i,provider_name){
995    var provider_obj = L.tileLayer.provider(provider_name);
996    // ulr
997    var url = provider_obj._url;
998    var options = {
999      id: provider_name,
1000      attribution: provider_obj.options.attribution
1001    };
1002    // variant
1003    if(provider_name.indexOf('.')>0) {
1004      var variant = provider_name.split('.')[1];
1005      url = url.replace('{variant}',variant);
1006    }
1007    // apikey
1008    if(provider_name.indexOf('Thunderforest')===0) {
1009      var apiKey = 'a6e1e765af684069ae4a4433f4e71c00';
1010      url = url.replace('{apikey}',apiKey);
1011    }
1012    // OpenTopoMap
1013    if(provider_name.indexOf('OpenTopoMap')===0) {
1014      options['maxZoom'] = [16];
1015    }
1016    // Esri.WorldImagery
1017    if(provider_name.indexOf('Esri')===0) {
1018      url = url.replace('WorldImagery','World_Imagery');
1019      options['maxZoom'] = [17];
1020    }
1021    // basemap
1022    if(provider_name.indexOf('BasemapAT')===0) {
1023      if(provider_name.indexOf('grau')>0) {
1024        url = url.replace('{format}','png');
1025        url = url.replace('grau','bmapgrau');
1026      } else if(provider_name.indexOf('orthofoto')>0) {
1027        url = url.replace('{format}','jpeg');
1028        url = url.replace('orthofoto','bmaporthofoto30cm');
1029      }
1030      options['subdomains'] = ["", "1", "2", "3", "4"];
1031      options['bounds'] = [[46.35877, 8.782379], [49.037872, 17.189532]];
1032    }
1033    provider[i] = L.tileLayer(url,options);
1034    baseMaps[provider_name] = provider[i];
1035  });
1036  return {providers: provider, baseMaps: baseMaps, currentIndex:currentIndex}
1037}

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.