jQuery събития: добавете предварително манипулатор за обратно извикване към вече съществуващи

На уеб страница има елементи с манипулатори за кликване и/или натискане на клавиш. Ако добавя нов, той ще се изпълни след тях. Имам нужда от начин да добавя ново обратно извикване, което е добавено към списъка с манипулатори на събития, така че да се изпълни предварително. Как е възможно това с jQuery?

Актуализация

Защо не мога просто да използвам метода за развързване на jQuery? Инжектирам своя jQuery код във всяка уеб страница, така че да не знам дали има и коя рамка на JavaScript се използва. Имам нужда от универсален начин за откриване на манипулатори на събития и предваряване на моя. (Преди да попитате, изграждам приложение за „рекордер“, което проследява действията на потребителите, за да ги съхранява и да ги изпълнява по-късно.)

Актуализация 2

Използвам само Firefox, няма нужда от съвместимост с IE. Трябва да изчакам страницата да се зареди напълно и след това моят jQuery скрипт ще бъде извикан.


person Alp    schedule 29.01.2012    source източник
comment
дали това е скрипт, върху който имате контрол? с други думи, можете ли да развържете и след това да обвържете отново всичко?   -  person kinakuta    schedule 29.01.2012
comment
обратното извикване винаги се изпълнява след събитие. ако искате старият ви манипулатор да направи нещо допълнително, защо просто не промените кода в съществуващия си манипулатор?   -  person Benny Tjia    schedule 29.01.2012
comment
Доколкото разбирам, няма начин да се гарантира в какъв ред ще бъдат извикани множество манипулатори, свързани с .addEventListener(), и няма начин да се изброят кои манипулатори са били обвързани. Една библиотека (като jQuery) може да заобиколи това, стига да обвързвате събития само през библиотеката, но не съм сигурен как бихте могли да се справите със събития, обвързани чрез множество библиотеки и/или обикновен JS. Освен ако не можете да замените .addEventListener() преди който и да е друг код на страницата да бъде изпълнен, така че други събития за обвързване на код да преминават през вашето прокси? (Което все още няма да ви помогне за по-стар IE...)   -  person nnnnnn    schedule 29.01.2012
comment
Няма нужда от съвместимост с IE, работи само във FF. Не мога да стартирам никакъв код в началото, трябва да изчакам страницата да се зареди и след това моят jQuery скрипт ще бъде зареден.   -  person Alp    schedule 29.01.2012
comment


Отговори (2)


Спрях се и на тази нужда и измислих заобиколно решение, което се основава на това как събитията се появяват в DOM. Така че основната идея е всъщност да направите следното:

  1. Вмъкнете допълнителен елемент като директно дете на елемента, към който искате да добавите събитието.

  2. В случай на събитие click се уверете, че то заема пълната ширина и височина на своя родител:

    • If the parent has padding/border add negative margin to the child so that it takes the full area of the parent
  3. Добавете предварително добавеното събитие за щракване към създаденото дете

Събитието за щракване се добавя предварително, тъй като щракването върху дъщерния елемент ще се изпълни първо и събитието се изпраща до родителя. Тогава съществуващите събития на родителя ще бъдат изпълнени след това, създавайки желания ефект.

Пример:

      
      const $someButton=$('.btn')
      $someButton.click(()=> alert('default event'))
      /**
      * 1. Insert an extra element 
      * as direct child of the element 
      * you want to append the event to
      **/
      $someButton.wrapInner(
        '<div class="btn__first_event"></div>'
      )
      /**
      * 3. Add the prepended click event to 
      * the created child
      **/
      $someButton.find('.btn__first_event').click(()=>alert('Prepended Event'))
.btn{
   cursor:pointer;
   background-color: yellow;
   padding:10px;
   border-radius:3px;
   border: 1px solid;
   display: inline-block;
}
/*
 2. In the case of click event 
make sure it takes 
the full width and 
height of its parent
-------------------- 
note: some css is needed for 
offsetting padding / border
*/
.btn__first_event{
   margin: -10px;
   padding: 1px;
   border-radius:3px;
   background-color: rgba(0, 0, 255, 0.4)
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="btn">Click me<div>

person Andreas    schedule 15.02.2021

Мисля, че това може да проработи, ако използвате улавяне на събития (манипулаторите на предци се извикват, преди събитието да достигне елемента) вместо бълбукане (дете --> предци). Това е начин за прихващане на събитие, преди целевият елемент да бъде достигнат.

Повечето манипулатори на събития използват балончета на събития. Според w3c едно събитие първо се улавя, а след това от целта се появява отново. Така че, ако обвържете събитие към документа с помощта на прихващане, то ще се изпълни първо за всеки елемент на страницата.

http://www.w3.org/TR/2000/REC-DOM-Level-2-Events-20001113/events.html#Events-flow-capture

Бихте обвързали манипулатора с: (третият аргумент е дали искате да използвате прихващане на събития)

document.body.addEventListener('click',handler,true)

Това ще се изпълнява за всяко щракване в елемента, преди да се изпълни манипулаторът на събитието на щракнатия елемент. Не съм сигурен обаче за поддръжката в браузърите.

person Roel    schedule 29.01.2012
comment
Това изглежда работи, благодаря. Въпреки че вярвам, че няма да обхване всички възможни случаи. - person Alp; 29.01.2012