PageSourceSearch

https://pnth-terreenaction.org/eco-jardins/javascripts/yeswiki-base.js?v=4.6.7

js pnth-terreenaction.org collected 2026-09-26 07:36:12 UTC 30,695 bytes, 1,000 lines download raw bytes

1const DATATABLE_OPTIONS = {
2  // responsive: true,
3  paging: false,
4  language: {
5    sProcessing: _t('DATATABLES_PROCESSING'),
6    sSearch: _t('DATATABLES_SEARCH'),
7    sLengthMenu: _t('DATATABLES_LENGTHMENU'),
8    sInfo: _t('DATATABLES_INFO'),
9    sInfoEmpty: _t('DATATABLES_INFOEMPTY'),
10    sInfoFiltered: _t('DATATABLES_INFOFILTERED'),
11    sInfoPostFix: '',
12    sLoadingRecords: _t('DATATABLES_LOADINGRECORDS'),
13    sZeroRecords: _t('DATATABLES_ZERORECORD'),
14    sEmptyTable: _t('DATATABLES_EMPTYTABLE'),
15    oPaginate: {
16      sFirst: _t('FIRST'),
17      sPrevious: _t('PREVIOUS'),
18      sNext: _t('NEXT'),
19      sLast: _t('LAST'),
20    },
21    oAria: {
22      sSortAscending: _t('DATATABLES_SORTASCENDING'),
23      sSortDescending: _t('DATATABLES_SORTDESCENDING'),
24    },
25  },
26  fixedHeader: {
27    header: true,
28    footer: false,
29  },
30  dom:
31    "<'row'<'col-sm-6'l><'col-sm-6'f>>" +
32    "<'row'<'col-sm-12'tr>>" +
33    "<'row'<'col-sm-6'i><'col-sm-6'<'pull-right'B>>>",
34  buttons: [
35    {
36      extend: 'copy',
37      className: 'btn btn-default',
38      text: `<i class="far fa-copy"></i> ${_t('COPY')}`,
39    },
40    {
41      extend: 'csv',
42      className: 'btn btn-default',
43      text: '<i class="fas fa-file-csv"></i> CSV',
44    },
45    {
46      extend: 'print',
47      className: 'btn btn-default',
48      text: `<i class="fas fa-print"></i> ${_t('PRINT')}`,
49    },
50    // {
51    //   extend: 'colvis',
52    //   text: _t('DATATABLES_COLS_TO_DISPLAY')
53    // },
54  ],
55}
56
57function toastMessage(
58  message,
59  duration = 3000,
60  toastClass = 'alert alert-secondary-1',
61) {
62  const innerEl = document.createElement('div')
63  innerEl.className = toastClass
64  innerEl.textContent = message
65  const toastEl = document.createElement('div')
66  toastEl.className = 'toast-message'
67  toastEl.appendChild(innerEl)
68  const $toast = $(toastEl)
69  $('body').after($toast)
70  $toast.css('top', `${$('#yw-topnav').outerHeight(true) + 20}px`)
71  $toast.css('opacity', 1)
72  setTimeout(() => {
73    $toast.css('opacity', 0)
74  }, duration)
75  setTimeout(() => {
76    $toast.remove()
77  }, duration + 300)
78  $toast.addClass('visible')
79}
80// polyfill placeholder
81;(function ($) {
82  $('input[type=password]').each(function () {
83    const vMe = $(this)
84
85    $('<div>')
86      .addClass('far fa-eye')
87      .attr('title', _t('SHOW_PASSWORD'))
88      .css({
89        position: 'absolute',
90        right: '0%',
91        top: '50%',
92        transform: 'translate(0px, -50%)',
93        paddingRight: '1em',
94        fontSize: '1em',
95      })
96      .on('click', function () {
97        if (vMe.attr('type') == 'password') {
98          vMe.attr('type', 'text')
99          $(this)
100            .removeClass('fa-eye')
101            .attr('title', _t('HIDE_PASSWORD'))
102            .addClass('fa-eye-slash')
103        } else {
104          vMe.attr('type', 'password')
105          $(this)
106            .addClass('fa-eye')
107            .removeClass('fa-eye-slash')
108            .attr('title', _t('SHOW_PASSWORD'))
109        }
110      })
111      .insertAfter($(this))
112  })
113
114  // gestion des classes actives pour les menus
115  $('a.active-link')
116    .parent()
117    .addClass('active-list')
118    .parents('ul')
119    .prev('a')
120    .addClass('active-parent-link')
121    .parent()
122    .addClass('active-list')
123
124  function addIframeHandlerTo(url) {
125    const regexHasHandler = new RegExp(/\??.*\/(edit)?iframe(&.*)?/g)
126    const regexOnDomain = new RegExp(`^${wiki.baseUrl}`)
127    if (regexHasHandler.test(url)) {
128      return url
129    }
130    if (regexOnDomain.test(url)) {
131      return `${url}/iframe`
132    }
133    return url
134  }
135
136  // fenetres modales
137  function openModal(e) {
138    e.stopPropagation()
139    e.preventDefault()
140    const $this = $(this)
141    const titleText = $this.attr('title') || ''
142    const size = ` ${$this.data('size')}`
143    const iframe = $this.data('iframe')
144
145    let $modal = $('#YesWikiModal')
146    const yesWikiModalHtml = `
147      <div class="modal-dialog${size} ${$this.data('header') === false ? 'no-header' : ''}">
148        <div class="modal-content">
149          <div class="modal-header">
150            <button type="button" class="close" data-dismiss="modal">&times;</button>
151            <h3></h3>
152          </div>
153          <div class="modal-body"></div>
154          <button type="button" class="no-header-btn-close" data-dismiss="modal">&times;</button>
155        </div>
156      </div>`
157
158    if ($modal.length === 0) {
159      $('body').append(
160        `<div class="modal fade" id="YesWikiModal">${yesWikiModalHtml}</div>`,
161      )
162      $modal = $('#YesWikiModal')
163    } else {
164      $modal.html(yesWikiModalHtml)
165    }
166    if (titleText.length > 0) {
167      $modal.find('.modal-header h3').text($.trim(titleText))
168    }
169
170    let link = $this.attr('href')
171    if (/\.(gif|jpg|jpeg|tiff|png)$/i.test(link)) {
172      $modal
173        .find('.modal-body')
174        .html(
175          `<img loading="lazy" class="center-block img-responsive" src="${link}" alt="" />`,
176        )
177    } else if (iframe === 1) {
178      const modalTitle = $modal.find('.modal-header h3')
179      if (modalTitle.length > 0) {
180        const anchorText =
181          modalTitle[0].innerText === 0
182            ? link.substr(0, 128)
183            : modalTitle[0].innerText
184        $(modalTitle[0])
185          .empty()
186          .append($('<a>').attr('href', link).text(anchorText))
187      }
188      link = addIframeHandlerTo(link)
189      $modal
190        .find('.modal-body')
191        .html(
192          '<span id="yw-modal-loading" class="throbber"></span>' +
193            `<iframe id="yw-modal-iframe" src="${link}" referrerpolicy="no-referrer"></iframe>`,
194        )
195      $('#yw-modal-iframe').on('load', () => {
196        $('#yw-modal-loading').hide()
197      })
198    } else {
199      // incomingurl can be usefull (per example for deletepage handler)
200      try {
201        const url = document.createElement('a')
202        url.href = link
203        const queryString = url.search
204        let separator
205        if (!queryString || queryString.length === 0) {
206          separator = '?'
207        } else {
208          separator = '&'
209        }
210        link += `${separator}incomingurl=${encodeURIComponent(
211          window.location.toString(),
212        )}`
213      } catch (er) {
214        console.error(er)
215      }
216      // AJAX Request for javascripts
217      const xhttp = new XMLHttpRequest()
218      xhttp.onreadystatechange = function () {
219        if (this.readyState === 4 && this.status === 200) {
220          const xmlString = this.responseText
221          const doc = new DOMParser().parseFromString(xmlString, 'text/html')
222          // find scripts
223          const res = doc.scripts
224          const l = res.length
225          let i
226          for (i = 0; i < l; i++) {
227            const src = res[i].getAttribute('src')
228            if (src) {
229              var selection = document.querySelectorAll(`script[src="${src}"]`)
230              if (!selection || selection.length == 0) {
231                // append script and load it only if not present
232                if (res[i].type === 'module') {
233                  const newScript = document.createElement('script')
234                  newScript.type = 'module'
235                  newScript.src = src
236                  document.body.appendChild(newScript)
237                } else {
238                  document.body.appendChild(document.importNode(res[i]))
239                  $.getScript(src)
240                }
241              }
242            } else {
243              const script = res[i].innerHTML
244              // select all script of current page without src
245              const pageScripts = document.scripts
246              const selLenght = pageScripts.length
247              var j
248              for (j = 0; j < selLenght; j++) {
249                if (
250                  !pageScripts[j].hasAttribute('src') &&
251                  script != pageScripts[j].innerHTML
252                ) {
253                  const newScript = document.importNode(res[i])
254                  document.body.appendChild(newScript)
255                }
256              }
257            }
258          }
259          // find css
260          const importedCSS = doc.querySelectorAll('link[rel="stylesheet"]')
261          const le = importedCSS.length
262          for (i = 0; i < le; i++) {
263            const href = importedCSS[i].getAttribute('href')
264            if (href) {
265              const existingLink = document.querySelector(
266                `link[href="${href}"]`,
267              )
268              if (!existingLink || existingLink.length === 0) {
269                // append link
270                document.body.appendChild(document.importNode(importedCSS[i]))
271              }
272            }
273          }
274          // AJAX Request for content
275          $modal.find('.modal-body').load(`${link} .page`, () => {
276            $(document).trigger('yw-modal-open')
277            return false
278          })
279        }
280      }
281      xhttp.open('GET', link, true)
282      xhttp.send()
283    }
284    $modal
285      .modal({ keyboard: false })
286      .modal('show')
287      .on('hidden hidden.bs.modal', () => {
288        $modal.remove()
289      })
290
291    return false
292  }
293  $(document).on('click', 'a.modalbox, a.modal, .modalbox a', openM
293odal)
294
295  $(document).on('click', 'a.newtab', function (e) {
296    e.preventDefault()
297    window.open($(this).attr('href'), '_blank')
298  })
299
300  // on change l'icone de l'accordeon
301  $('.accordion-trigger').on('click', function () {
302    if ($(this).next().find('.collapse').hasClass('in')) {
303      $(this).find('.arrow').html('&#9658;')
304    } else {
305      $(this).find('.arrow').html('&#9660;')
306    }
307  })
308
309  // on enleve la fonction doubleclic dans des cas ou cela pourrait etre indesirable
310  $('.no-dblclick, form, .page a, button, .dropdown-menu').on(
311    'dblclick',
312    (_e) => false,
313  )
314
315  // deplacer les fenetres modales en bas de body pour eviter que des styles s'appliquent
316  $('.modal').appendTo(document.body)
317
318  // Remove hidden div by ACL
319  $('.remove-this-div-on-page-load').remove()
320
321  /* tooltips */
322  $("[data-toggle='tooltip']").tooltip()
323  $("[data-tooltip='tooltip']").tooltip()
324
325  // moteur de recherche utilisé dans un template
326  $('a[href="#search"]').on('click', function (e) {
327    e.preventDefault()
328    $(this).siblings('#search').addClass('open')
329    $(this).siblings('#search').find('.search-query').focus()
330  })
331
332  $('#search, #search button.close-search').on('click keyup', function (e) {
333    if (
334      e.target == this ||
335      $(e.target).hasClass('close-search') ||
336      e.keyCode == 27
337    ) {
338      $(this).removeClass('open')
339    }
340  })
341
342  // se souvenir des tabs navigués
343  $.fn.historyTabs = function () {
344    const that = this
345    window.addEventListener('popstate', (event) => {
346      if (event.state) {
347        $(that).filter(`[href="${event.state.url}"]`).tab('show')
348      }
349    })
350    return this.each(function (index, element) {
351      $(element).on('show.bs.tab', function () {
352        const stateObject = { url: $(this).attr('href') }
353
354        if (window.location.hash && stateObject.url !== window.location.hash) {
355          window.history.pushState(
356            stateObject,
357            document.title,
358            window.location.pathname +
359              window.location.search +
360              $(this).attr('href'),
361          )
362        } else {
363          window.history.replaceState(
364            stateObject,
365            document.title,
366            window.location.pathname +
367              window.location.search +
368              $(this).attr('href'),
369          )
370        }
371      })
372      if (!window.location.hash && $(element).is('.active')) {
373        // Shows the first element if there are no query parameters.
374        $(element).tab('show')
375      } else if ($(this).attr('href') === window.location.hash) {
376        $(element).tab('show')
377      }
378    })
379  }
380  $('a[data-toggle="tab"]').historyTabs()
381
382  // double clic
383  $('.navbar').on('dblclick', function (e) {
384    e.stopPropagation()
385    $('body').append(
386      '<div class="modal fade" id="YesWikiModal">' +
387        '<div class="modal-dialog">' +
388        '<div class="modal-content">' +
389        '<div class="modal-header">' +
390        '<button type="button" class="close" data-dismiss="modal">&times;</button>' +
391        `<h3>${_t('NAVBAR_EDIT_MESSAGE')}</h3>` +
392        '</div>' +
393        '<div class="modal-body">' +
394        '</div>' +
395        '</div>' +
396        '</div>' +
397        '</div>',
398    )
399
400    const $editmodal = $('#YesWikiModal')
401    $(this)
402      .find('.include')
403      .each(function () {
404        const href = $(this)
405          .attr('ondblclick')
406          .replace("document.location='", '')
407          .replace("';", '')
408        const pagewiki = href
409          .replace('/edit', '')
410          .replace('http://yeswiki.dev/wakka.php?wiki=', '')
411        $editmodal
412          .find('.modal-body')
413          .append(
414            `<a href="${href}" class="btn btn-default btn-block">` +
415              `<i class="fa fa-pencil-alt"></i> ${_t(
416                'YESWIKIMODAL_EDIT_MSG',
417              )} ${pagewiki}</a>`,
418          )
419      })
420
421    $editmodal
422      .find('.modal-body')
423      .append(
424        `<a href="#" data-dismiss="modal" class="btn btn-warning btn-xs btn-block">${+_t(
425          'EDIT_OUPS_MSG',
426        )}</a>`,
427      )
428
429    $editmodal
430      .modal({ keyboard: true })
431      .modal('show')
432      .on('hidden hidden.bs.modal', () => {
433        $editmodal.remove()
434      })
435
436    return false
437  })
438
439  // AUTO RESIZE IFRAME
440  const iframes = $('iframe.auto-resize')
441  if (iframes.length > 0) {
442    $.getScript('javascripts/vendor/iframe-resizer/iframeResizer.min.js')
443      .done((_script, _textStatus) => {
444        iframes.iFrameResize()
445      })
446      .fail((jqxhr, settings, exception) => {
447        console.log(
448          'Error getting script javascripts/vendor/iframe-resizer/iframeResizer.min.js',
449          exception,
450        )
451      })
452  }
453
454  // get the html from a yeswiki page
455  function getText(url, link) {
456    let html
457    $.get(url, (data) => {
458      html = data
459    }).done(() => {
460      link.attr('data-content', html)
461    })
462  }
463
464  $('.modalbox-hover').each(function () {
465    getText(`${$(this).attr('href')}/html`, $(this))
466  })
467  $('.modalbox-hover').popover({
468    trigger: 'hover',
469    html: true, // permet d'utiliser du html
470    placement: 'right', // position de la popover (top ou bottom ou left ou right)
471  })
472
473  // ouvrir les liens dans une nouvelle fenetre
474  $('.new-window').attr('target', '_blank')
475  $(document).on('yw-modal-open', () => {
476    $('.new-window:not([target])').attr('target', '_blank')
477  })
478
479  // acl switch
480  $('#acl-switch-mode')
481    .change(function () {
482      if ($(this).prop('checked')) {
483        // show advanced
484        $('.acl-simple').hide().val(null)
485        $('.acl-advanced').slideDown()
486      } else {
487        $('.acl-single-container label').each(function () {
488          $(this).after($(`select[name=${$(this).data('input')}]`))
489        })
490        $('.acl-simple').show()
491        $('.acl-advanced').hide().val(null)
492      }
493    })
494    .trigger('change')
495
496  // tables
497  if (typeof $('.table').DataTable === 'function') {
498    $('.table:not(.prevent-auto-init)').DataTable(DATATABLE_OPTIONS)
499  }
500
501  /** comments */
502  const $comments = $('.yeswiki-page-comments, #post-comment')
503
504  function resetCommentForm(form) {
505    form
506      .attr('id', 'post-comment')
507      .attr('class', '')
508      .attr(
509        'action',
510        form.attr('action').replace(/api\/comments(\/.*)/gm, 'api/comments'),
511      )
512      .appendTo($('.yeswiki-page-comments').parent())
513      .find('label')
514      .removeClass('hide')
515    $('.btn-cancel-comment').remove()
516    $('#post-comment').find('.btn-post-comment').text(_t('SAVE'))
517    window['aceditor-body'].editor.setValue('')
518  }
519
520  // ajax post comment
521  $comments.on('click', '.btn-post-comment', function (e) {
522    e.preventDefault()
523    const form = $(this).parent('form')
524    const urlpost = form.attr('action')
525    $.ajax({
526      type: 'POST',
527      url: urlpost,
528      data: form.serialize(),
529      dataType: 'json',
530      success(e) {
531        form.trigger('reset')
532        window['aceditor-body'].editor.setValue('')
533        toastMessage(e.success, 3000, 'alert alert-success')
534        form.parents('.yw-comment').find('.comment-links').removeClass('hide')
535        // we place the new comment in different places if its an answer, a modification or a new comment
536        if (form.hasClass('comment-modify')) {
537          form
538            .closest('.yw-comment')
539            .html($('<div>').html(e.html).find('.yw-comment').html())
540          resetCommentForm(form)
541        } else if (form.parent().hasClass('comment-reponses')) {
542          form.parent().append(e.html)
543          resetCommentForm(form)
544        } else {
545          $('.yeswiki-page-comments').append(e.html)
546        }
547      },
548      error(e) {
549        toastMessage(e.responseJSON.error, 3000, 'alert alert-danger')
550      },
551    })
552    return false
553  })
554
555  // ajax answer comment
556  $comments.on('click', '.btn-answer-comment', function (e) {
557    e.preventDefault()
558    const com = $(this).parent().parent()
559    $('.temporary-form')
560      .parents('.yw-comment')
561      .find('.comment-html:first')
562      .removeClass('hide')
563    $('.temporary-form')
564      .parents('.yw-comment')
565      .find('.comment-links:first')
566      .removeClass('hide')
567    // a comment-form is already opened
568    if ($('.temporary-form').length > 0) {
569      resetCommentForm($('.temporary-form'))
570    }
571
572    // clone comment form and change some options
573    const formAnswer = com.find('.comment-reponses:first')
574    $('#post-comment').appendTo(formAnswer)
575    formAnswer
576      .find('form')
577      .attr('id', `form-comment-${com.data('tag')}`)
578      .removeClass('hide')
579      .addClass('temporary-form')
580    formAnswer.find('[name="pagetag"]').val(com.data('tag'))
581    formAnswer
582      .find('form')
583      .append(
584        `<button class="btn-cancel-comment btn btn-sm btn-default">${_t('CANCEL')}</button>`,
585      )
586    com.find('.comment-links').addClass('hide')
587    com.find('label').addClass('hide')
588
589    return false
590  })
591
592  // ajax edit comment
593  $comments.on('click', '.btn-edit-comment', function (e) {
594    e.preventDefault()
595    const com = $(this).parent().parent()
596
597    // hide comment and comment links while editor is open
598    com.find('.comment-html:first').addClass('hide')
599    com.find('.comment-links:first').addClass('hide')
600
601    $('.temporary-form')
602      .parents('.yw-comment')
603      .find('.comment-html:first')
604      .removeClass('hide')
605    $('.temporary-form')
606      .parents('.yw-comment')
607      .find('.comment-links:first')
608      .removeClass('hide')
609    // a comment-form is already opened
610    if ($('.temporary-form').length > 0) {
611      resetCommentForm($('.temporary-form'))
612    }
613
614    // clone comment form and change some options
615    const formcom = com.find('.form-comment:first')
616    $('#post-comment').appendTo(formcom)
617    formcom
618      .find('form')
619      .attr('id', `form-comment-${com.data('tag')}`)
620      .attr(
621        'action',
622        `${formcom.find('form').attr('action')}/${com.data('tag')}`,
623      )
624      .removeClass('hide')
625      .addClass('temporary-form')
626      .addClass('comment-modify')
627    formcom.find('label').addClass('hide')
628    window['aceditor-body'].editor.setValue(com.find('.comment-body').val())
629    formcom.find('[name="pagetag"]').val(com.data('commenton'))
630    formcom.find('.btn-post-comment').text(_t('MODIFY'))
631    formcom
632      .find('form')
633      .append(
634        `<button class="btn-cancel-comment btn btn-sm btn-default">${_t('CANCEL')}</button>`,
635      )
636    com.parents('.yw-comment').find('.comment-links').addClass('hide')
637
638    return false
639  })
640
641  // cancel comment edit
642  $comments.on('click', '.btn-cancel-comment', function (e) {
643    e.preventDefault()
644    const com = $(this).parent().parent().parent()
645    // restore html comment and links
646    com.find('.comment-html:first').removeClass('hide')
647    com.find('.comment-links:first').removeClass('hide')
648    com.parents('.yw-comment').find('.comment-links').removeClass('hide')
649    resetCommentForm($(`#form-comment-${com.data('tag')}`))
650    return false
651  })
652
653  // ajax delete comment
654  $comments.on('click', '.btn-delete-comment', function (e) {
655    if (confirm(_t('DELETE_COMMENT_AND_ANSWERS'))) {
656      e.preventDefault()
657      const link = $(this)
658      $.ajax({
659        type: 'POST',
660        url: link.attr('href'),
661        dataType: 'json',
662        success(e) {
663          link.closest('.yw-comment').slideUp(250, function () {
664            $(this).remove()
665          })
666          toastMessage(e.success, 3000, 'alert alert-success')
667        },
668        error(e) {
669          toastMessage(e.responseJSON.error, 3000, 'alert alert-danger')
670        },
671      })
672    }
673    return false
674  })
675  // reaction
676
677  // init user reaction count
678  $('.reactions-container').each((i, val) => {
679    const userReaction = $(val).find('.user-reaction').length
680    const nbReactionLeft = $(val).find('.max-reaction').text()
681    $(val)
682      .find('.max-reaction')
683      .text(nbReactionLeft - userReaction)
684  })
685
686  // Reaction Management Helper
687  const reactionManagementHelper = {
688    renderAjaxError(translation, jqXHR, textStatus, errorThrown) {
689      const message = _t(translation, {
690        error: `${textStatus} / ${errorThrown}${jqXHR.responseJSON.error != null ? `:${jqXHR.responseJSON.error}` : ''}`,
691      })
692      if (typeof toastMessage == 'function') {
693        toastMessage(message, 3000, 'alert alert-danger')
694      } else {
695        alert(message)
696      }
697      if (jqXHR.responseJSON.exceptionMessage != null) {
698        console.warn(jqXHR.responseJSON.exceptionMessage)
699      }
700    },
701    deleteATag(elem) {
702      const url = $(elem).attr('href')
703      $.ajax({
704        method: 'GET',
705        url,
706        success() {
707          const table = $(elem).closest('table')
708          if (table.length != 0) {
709            console.log(table.DataTable())
710            table.DataTable().row($(elem).closest('tr')).remove().draw()
711          }
712        },
713        error(jqXHR, textStatus, errorThrown) {
714          reactionManagementHelper.renderAjaxError(
715            'REACTION_NOT_POSSIBLE_TO_DELETE_REACTION',
716            jqXHR,
717            textStatus,
718            errorThrown,
719          )
720        },
721      })
722    },
723    deleteTags(headElem) {
724      const table = $(headElem).closest('table')
725      if (table.length != 0) {
726        $(table)
727          .find('.btn-delete-reaction:not(.btn-delete-all)')
728          .each(function () {
729            reactionManagementHelper.deleteATag($(this))
730          })
731      }
732    },
733  }
734
735  // handler reaction click
736  $('.link-reaction').click(function (event) {
737    event.preventDefault()
738    event.stopPropagation()
739    const extractData = (item) => {
740      const nb = $(item).find('.reaction-numbers')
741      return {
742        url: $(item).attr('href'),
743        data: $(item).data(),
744        nb,
745        nbInit: parseInt(nb.text()),
746      }
747    }
748    const { url, data, nb, nbInit } = extractData(this)
749    const deleteUserReaction = async (url, data, nb, nbInit, link) => {
750      const p = new Promise((resolve, reject) => {
751        let currentReactionId = data.reactionid
752        if ('oldId' in data && (data.oldId === true || data.oldId === 'true')) {
753          currentReactionId = 'reactionField'
754        }
755        $.ajax({
756          method: 'GET',
757          url: `${url}/${currentReactionId}/${data.id}/${data.pagetag}/${data.username}/delete`,
758          success() {
759            nb.text(nbInit - 1)
760            $(link).removeClass('user-reaction')
761            const nbReactionLeft = parseFloat(
762              $(link)
763                .parents('.reactions-container')
764                .find('.max-reaction')
765                .text(),
766            )
767            $(link)
768              .parents('.reactions-container')
769              .find('.max-reaction')
770              .text(nbReactionLeft + 1)
771            resolve()
772          },
773          error(jqXHR, textStatus, errorThrown) {
774            reactionManagementHelper.renderAjaxError(
775              'REACTION_NOT_POSSIBLE_TO_DELETE_REACTION',
776              jqXHR,
777              textStatus,
778              errorThrown,
779            )
780            reject()
781          },
782        })
783      })
784      return await p.then((...args) => Promise.resolve(...args))
785    }
786    if (url !== '#') {
787      if ($(this).hasClass('user-reaction')) {
788        // on supprime la reaction
789        if (typeof blockReactionRemove !== 'undefined' && blockReactionRemove) {
790          if (blockReactionRemoveMessage) {
791            if (typeof toastMessage == 'function') {
792              toastMessage(
793                blockReactionRemoveMessage,
794                3000,
795                'alert alert-warning',
796              )
797            } else {
798              alert(blockReactionRemoveMessage)
799            }
800          }
801          return false
802        }
803        const link = $(this)
804        deleteUserReaction(url, data, nb, nbInit, link).catch((_e) => {
805          /* do nothing */
806        })
807        return false
808      }
809      // on ajoute la reaction si le max n'est pas dépassé
810      const nbReactionLeft = parseFloat(
811        $(this).parents('.reactions-container').find('.max-reaction').text(),
812      )
813      if (
814        url !== '#' &&
815        nbReactionLeft == 0 &&
816        typeof blockReactionRemove !== 'undefined' &&
817        blockReactionRemove === true
818      ) {
819        const previous = $(this)
820          .closest('.reactions-flex')
821          .find('.user-reaction')
822          .first()
823        if (
824          typeof previous === 'object' &&
825          'length' in previous &&
826          previous.length > 0
827        ) {
828          const {
829            url: previousUrl,
830            data: previousData,
831            nb: previousNb,
832            nbInit: previousNbInit,
833          } = extractData(previous)
834          if (previousUrl !== '#') {
835            deleteUserReaction(
836              previousUrl,
837              previousData,
838              previousNb,
839              previousNbInit,
840              $(previous),
841            )
842              .then(() => {
843                $(this).click()
844              })
845              .catch((_e) => {
846                /* do nothing */
847              })
848            return false
849          }
850        }
851      }
852      if (nbReactionLeft > 0) {
853        const link = $(this)
854        $.ajax({
855          method: 'POST',
856          url,
857          data,
858          success() {
859            $(link)
860              .find('.reaction-numbers')
861              .text(nbReactionLeft - 1)
862
863            nb.text(nbInit + 1)
864            $(link).addClass('user-reaction')
865            $(link)
866              .parents('.reactions-container')
867              .find('.max-reaction')
868              .text(nbReactionLeft - 1)
869          },
870          error(jqXHR, textStatus, errorThrown) {
871            reactionManagementHelper.renderAjaxError(
872              'REACTION_NOT_POSSIBLE_TO_ADD_REACTION',
873              jqXHR,
874              textStatus,
875              errorThrown,
876            )
877          },
878        })
879      } else {
880        const message =
881          "Vous n'avez plus de choix possibles, vous pouvez retirer un choix existant pour changer"
882        if (typeof toastMessage == 'function') {
883          toastMessage(message, 3000, 'alert alert-warning')
884        } else {
885          alert(message)
886        }
887      }
888      return false
889    }
890  })
891
892  $('.btn-delete-reaction').on('click', function (e) {
893    e.preventDefault()
894    if (!$(this).hasClass('btn-delete-all')) {
895      if (confirm(_t('REACTION_CONFIRM_DELETE'))) {
896        reactionManagementHelper.deleteATag($(this))
897      }
898    } else if (confirm(_t('REACTION_CONFIRM_DELETE_ALL'))) {
899      reactionManagementHelper.deleteTags($(this))
900    }
901  })
902})(jQuery)
903
904// fot comments table
905$('#commentsTableDeleteModal.modal').on('shown.bs.modal', function (event) {
906  multiDeleteService.initProgressBar($(this))
907  $(this).find('.modal-body .multi-delete-results').html('')
908  const deleteButton = $(this).find('button.start-btn-delete-comment')
909  $(deleteButton).removeAttr('disabled')
910  const button = $(event.relatedTarget) // Button that triggered the modal
911  const name = $(button).data('name')
912  $(this).find('#commentToDelete').text(name)
913  $(deleteButton).data('name', name)
914  $(deleteButton).data('targetNode', button)
915  $(deleteButton).data('modal', this)
916  if (!$(deleteButton).hasClass('eventSet')) {
917    $(deleteButton).addClass('eventSet')
918    $(deleteButton).on('click', function () {
919      $(this).attr('disabled', 'disabled')
920      $(this).tooltip('hide')
921      const name = $(this).data('name')
922      const targetNode = $(this).data('targetNode')
923      const modal = $(this).data('modal')
924
925      $.ajax({
926        method: 'post',
927        url: wiki.url(`api/comments/${name}/delete`),
928        timeout: 30000, // 30 seconds
929        error(e) {
930          multiDeleteService.addErrorMessage(
931            $(modal),
932            `${_t('COMMENT_NOT_DELETED', { comment: name })} : ${
933              e.responseJSON && e.responseJSON.error ? e.responseJSON.error : ''
934            }`,
935          )
936        },
937        success() {
938          multiDeleteService.removeLine(
939            $(targetNode).closest('.dataTables_wrapper').prop('id'),
940            name,
941          )
942          $(modal)
943            .find('.modal-body .multi-delete-results')
944            .first()
945            .append($('<div>').text(_t('COMMENT_DELETED')))
946        },
947        complete() {
948          multiDeleteService.updateProgressBar($(modal), ['test'], 0)
949        },
950      })
951    })
952  }
953})
954
955// function to check all checkbox in page.
956function checkAll(state) {
957  const checkboxes = document.querySelectorAll('input.selectpage')
958  const newState = [true, 'true', 1, '1'].includes(state)
959  checkboxes.forEach((checkbox) => {
960    if (checkbox.type == 'checkbox') {
961      checkbox.checked = newState
962    }
963  })
964}
965
966// tabs
967// hack for next and previous buttons
968$('.tab-content [data-toggle="tab"]').on('click', function () {
969  const base = $(this).closest('.tab-content').prev()
970  $(base).find('.active').removeClass('active')
971  $(base)
972    .find(`[href="${$(this).attr('href')}"]`)
973    .parent()
974    .addClass('active')
975  $(base)
976    .find(`a[href="${$(this).attr('href')}"]`)
977    .tab('show')
978  // manage iframe case
979  if (window.location != parent.parent.location) {
980    $('html, body').animate({ scrollTop: $(base).offset().top }, 500)
981    try {
982      $(base).get(0).scrollIntoView()
983      window.parent.scrollBy(0, -80)
984    } catch (error) {
985      console.error(error)
986    }
987  } else {
988    $('html, body').animate({ scrollTop: $(base).offset().top - 80 }, 500)
989  }
990})
991
992// a11y
993$('#yw-a11y-jump-content').click(() => {
994  setTimeout(() => {
995    $('#yw-topnav').removeClass('nav-down').addClass('nav-up')
996    $('body').removeClass('nav-down').addClass('nav-up')
997  }, 300)
998})
999
1000window.checkAll = checkAll

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.