A place to cache linked articles (think custom and personal wayback machine)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

index.html 29KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582
  1. <!doctype html><!-- This is a valid HTML5 document. -->
  2. <!-- Screen readers, SEO, extensions and so on. -->
  3. <html lang=fr>
  4. <!-- Has to be within the first 1024 bytes, hence before the <title>
  5. See: https://www.w3.org/TR/2012/CR-html5-20121217/document-metadata.html#charset -->
  6. <meta charset=utf-8>
  7. <!-- Why no `X-UA-Compatible` meta: https://stackoverflow.com/a/6771584 -->
  8. <!-- The viewport meta is quite crowded and we are responsible for that.
  9. See: https://codepen.io/tigt/post/meta-viewport-for-2015 -->
  10. <meta name=viewport content="width=device-width,minimum-scale=1,initial-scale=1,shrink-to-fit=no">
  11. <!-- Required to make a valid HTML5 document. -->
  12. <title>Javascript - Event order (archive) — David Larlet</title>
  13. <!-- Generated from https://realfavicongenerator.net/ such a mess. -->
  14. <link rel="apple-touch-icon" sizes="180x180" href="/static/david/icons/apple-touch-icon.png">
  15. <link rel="icon" type="image/png" sizes="32x32" href="/static/david/icons/favicon-32x32.png">
  16. <link rel="icon" type="image/png" sizes="16x16" href="/static/david/icons/favicon-16x16.png">
  17. <link rel="manifest" href="/manifest.json">
  18. <link rel="mask-icon" href="/static/david/icons/safari-pinned-tab.svg" color="#5bbad5">
  19. <link rel="shortcut icon" href="/static/david/icons/favicon.ico">
  20. <meta name="apple-mobile-web-app-title" content="David Larlet">
  21. <meta name="application-name" content="David Larlet">
  22. <meta name="msapplication-TileColor" content="#da532c">
  23. <meta name="msapplication-config" content="/static/david/icons/browserconfig.xml">
  24. <meta name="theme-color" content="#f0f0ea">
  25. <!-- That good ol' feed, subscribe :p. -->
  26. <link rel=alternate type="application/atom+xml" title=Feed href="/david/log/">
  27. <meta name="robots" content="noindex, nofollow">
  28. <meta content="origin-when-cross-origin" name="referrer">
  29. <!-- Canonical URL for SEO purposes -->
  30. <link rel="canonical" href="http://www.quirksmode.org/js/events_order.html">
  31. <style>
  32. /* http://meyerweb.com/eric/tools/css/reset/ */
  33. html, body, div, span,
  34. h1, h2, h3, h4, h5, h6, p, blockquote, pre,
  35. a, abbr, address, big, cite, code,
  36. del, dfn, em, img, ins,
  37. small, strike, strong, tt, var,
  38. dl, dt, dd, ol, ul, li,
  39. fieldset, form, label, legend,
  40. table, caption, tbody, tfoot, thead, tr, th, td,
  41. article, aside, canvas, details, embed,
  42. figure, figcaption, footer, header, hgroup,
  43. menu, nav, output, ruby, section, summary,
  44. time, mark, audio, video {
  45. margin: 0;
  46. padding: 0;
  47. border: 0;
  48. font-size: 100%;
  49. font: inherit;
  50. vertical-align: baseline;
  51. }
  52. /* HTML5 display-role reset for older browsers */
  53. article, aside, details, figcaption, figure,
  54. footer, header, hgroup, menu, nav, section { display: block; }
  55. body { line-height: 1; }
  56. blockquote, q { quotes: none; }
  57. blockquote:before, blockquote:after,
  58. q:before, q:after {
  59. content: '';
  60. content: none;
  61. }
  62. table {
  63. border-collapse: collapse;
  64. border-spacing: 0;
  65. }
  66. /* http://practicaltypography.com/equity.html */
  67. /* https://calendar.perfplanet.com/2016/no-font-face-bulletproof-syntax/ */
  68. /* https://www.filamentgroup.com/lab/js-web-fonts.html */
  69. @font-face {
  70. font-family: 'EquityTextB';
  71. src: url('/static/david/css/fonts/Equity-Text-B-Regular-webfont.woff2') format('woff2'),
  72. url('/static/david/css/fonts/Equity-Text-B-Regular-webfont.woff') format('woff');
  73. font-weight: 300;
  74. font-style: normal;
  75. font-display: swap;
  76. }
  77. @font-face {
  78. font-family: 'EquityTextB';
  79. src: url('/static/david/css/fonts/Equity-Text-B-Italic-webfont.woff2') format('woff2'),
  80. url('/static/david/css/fonts/Equity-Text-B-Italic-webfont.woff') format('woff');
  81. font-weight: 300;
  82. font-style: italic;
  83. font-display: swap;
  84. }
  85. @font-face {
  86. font-family: 'EquityTextB';
  87. src: url('/static/david/css/fonts/Equity-Text-B-Bold-webfont.woff2') format('woff2'),
  88. url('/static/david/css/fonts/Equity-Text-B-Bold-webfont.woff') format('woff');
  89. font-weight: 700;
  90. font-style: normal;
  91. font-display: swap;
  92. }
  93. @font-face {
  94. font-family: 'ConcourseT3';
  95. src: url('/static/david/css/fonts/concourse_t3_regular-webfont-20190806.woff2') format('woff2'),
  96. url('/static/david/css/fonts/concourse_t3_regular-webfont-20190806.woff') format('woff');
  97. font-weight: 300;
  98. font-style: normal;
  99. font-display: swap;
  100. }
  101. /* http://practice.typekit.com/lesson/caring-about-opentype-features/ */
  102. body {
  103. /* http://www.cssfontstack.com/ Palatino 99% Win 86% Mac */
  104. font-family: "EquityTextB", Palatino, serif;
  105. background-color: #f0f0ea;
  106. color: #07486c;
  107. font-kerning: normal;
  108. -moz-osx-font-smoothing: grayscale;
  109. -webkit-font-smoothing: subpixel-antialiased;
  110. text-rendering: optimizeLegibility;
  111. font-variant-ligatures: common-ligatures contextual;
  112. font-feature-settings: "kern", "liga", "clig", "calt";
  113. }
  114. pre, code, kbd, samp, var, tt {
  115. font-family: 'TriplicateT4c', monospace;
  116. }
  117. em {
  118. font-style: italic;
  119. color: #323a45;
  120. }
  121. strong {
  122. font-weight: bold;
  123. color: black;
  124. }
  125. nav {
  126. background-color: #323a45;
  127. color: #f0f0ea;
  128. display: flex;
  129. justify-content: space-around;
  130. padding: 1rem .5rem;
  131. }
  132. nav:last-child {
  133. border-bottom: 1vh solid #2d7474;
  134. }
  135. nav a {
  136. color: #f0f0ea;
  137. }
  138. nav abbr {
  139. border-bottom: 1px dotted white;
  140. }
  141. h1 {
  142. border-top: 1vh solid #2d7474;
  143. border-bottom: .2vh dotted #2d7474;
  144. background-color: #e3e1e1;
  145. color: #323a45;
  146. text-align: center;
  147. padding: 5rem 0 4rem 0;
  148. width: 100%;
  149. font-family: 'ConcourseT3';
  150. display: flex;
  151. flex-direction: column;
  152. }
  153. h1.single {
  154. padding-bottom: 10rem;
  155. }
  156. h1 span {
  157. position: absolute;
  158. top: 1vh;
  159. left: 20%;
  160. line-height: 0;
  161. }
  162. h1 span a {
  163. line-height: 1.7;
  164. padding: 1rem 1.2rem .6rem 1.2rem;
  165. border-radius: 0 0 6% 6%;
  166. background: #2d7474;
  167. font-size: 1.3rem;
  168. color: white;
  169. text-decoration: none;
  170. }
  171. h2 {
  172. margin: 4rem 0 1rem;
  173. border-top: .2vh solid #2d7474;
  174. padding-top: 1vh;
  175. }
  176. h3 {
  177. text-align: center;
  178. margin: 3rem 0 .75em;
  179. }
  180. hr {
  181. height: .4rem;
  182. width: .4rem;
  183. border-radius: .4rem;
  184. background: #07486c;
  185. margin: 2.5rem auto;
  186. }
  187. time {
  188. display: bloc;
  189. margin-left: 0 !important;
  190. }
  191. ul, ol {
  192. margin: 2rem;
  193. }
  194. ul {
  195. list-style-type: square;
  196. }
  197. a {
  198. text-decoration-skip-ink: auto;
  199. text-decoration-thickness: 0.05em;
  200. text-underline-offset: 0.09em;
  201. }
  202. article {
  203. max-width: 50rem;
  204. display: flex;
  205. flex-direction: column;
  206. margin: 2rem auto;
  207. }
  208. article.single {
  209. border-top: .2vh dotted #2d7474;
  210. margin: -6rem auto 1rem auto;
  211. background: #f0f0ea;
  212. padding: 2rem;
  213. }
  214. article p:last-child {
  215. margin-bottom: 1rem;
  216. }
  217. p {
  218. padding: 0 .5rem;
  219. margin-left: 3rem;
  220. }
  221. p + p,
  222. figure + p {
  223. margin-top: 2rem;
  224. }
  225. blockquote {
  226. background-color: #e3e1e1;
  227. border-left: .5vw solid #2d7474;
  228. display: flex;
  229. flex-direction: column;
  230. align-items: center;
  231. padding: 1rem;
  232. margin: 1.5rem;
  233. }
  234. blockquote cite {
  235. font-style: italic;
  236. }
  237. blockquote p {
  238. margin-left: 0;
  239. }
  240. figure {
  241. border-top: .2vh solid #2d7474;
  242. background-color: #e3e1e1;
  243. text-align: center;
  244. padding: 1.5rem 0;
  245. margin: 1rem 0 0;
  246. font-size: 1.5rem;
  247. width: 100%;
  248. }
  249. figure img {
  250. max-width: 250px;
  251. max-height: 250px;
  252. border: .5vw solid #323a45;
  253. padding: 1px;
  254. }
  255. figcaption {
  256. padding: 1rem;
  257. line-height: 1.4;
  258. }
  259. aside {
  260. display: flex;
  261. flex-direction: column;
  262. background-color: #e3e1e1;
  263. padding: 1rem 0;
  264. border-bottom: .2vh solid #07486c;
  265. }
  266. aside p {
  267. max-width: 50rem;
  268. margin: 0 auto;
  269. }
  270. /* https://fvsch.com/code/css-locks/ */
  271. p, li, pre, code, kbd, samp, var, tt, time, details, figcaption {
  272. font-size: 1rem;
  273. line-height: calc( 1.5em + 0.2 * 1rem );
  274. }
  275. h1 {
  276. font-size: 1.9rem;
  277. line-height: calc( 1.2em + 0.2 * 1rem );
  278. }
  279. h2 {
  280. font-size: 1.6rem;
  281. line-height: calc( 1.3em + 0.2 * 1rem );
  282. }
  283. h3 {
  284. font-size: 1.35rem;
  285. line-height: calc( 1.4em + 0.2 * 1rem );
  286. }
  287. @media (min-width: 20em) {
  288. /* The (100vw - 20rem) / (50 - 20) part
  289. resolves to 0-1rem, depending on the
  290. viewport width (between 20em and 50em). */
  291. p, li, pre, code, kbd, samp, var, tt, time, details, figcaption {
  292. font-size: calc( 1rem + .6 * (100vw - 20rem) / (50 - 20) );
  293. line-height: calc( 1.5em + 0.2 * (100vw - 50rem) / (20 - 50) );
  294. margin-left: 0;
  295. }
  296. h1 {
  297. font-size: calc( 1.9rem + 1.5 * (100vw - 20rem) / (50 - 20) );
  298. line-height: calc( 1.2em + 0.2 * (100vw - 50rem) / (20 - 50) );
  299. }
  300. h2 {
  301. font-size: calc( 1.5rem + 1.5 * (100vw - 20rem) / (50 - 20) );
  302. line-height: calc( 1.3em + 0.2 * (100vw - 50rem) / (20 - 50) );
  303. }
  304. h3 {
  305. font-size: calc( 1.35rem + 1.5 * (100vw - 20rem) / (50 - 20) );
  306. line-height: calc( 1.4em + 0.2 * (100vw - 50rem) / (20 - 50) );
  307. }
  308. }
  309. @media (min-width: 50em) {
  310. /* The right part of the addition *must* be a
  311. rem value. In this example we *could* change
  312. the whole declaration to font-size:2.5rem,
  313. but if our baseline value was not expressed
  314. in rem we would have to use calc. */
  315. p, li, pre, code, kbd, samp, var, tt, time, details, figcaption {
  316. font-size: calc( 1rem + .6 * 1rem );
  317. line-height: 1.5em;
  318. }
  319. p, li, pre, details {
  320. margin-left: 3rem;
  321. }
  322. h1 {
  323. font-size: calc( 1.9rem + 1.5 * 1rem );
  324. line-height: 1.2em;
  325. }
  326. h2 {
  327. font-size: calc( 1.5rem + 1.5 * 1rem );
  328. line-height: 1.3em;
  329. }
  330. h3 {
  331. font-size: calc( 1.35rem + 1.5 * 1rem );
  332. line-height: 1.4em;
  333. }
  334. figure img {
  335. max-width: 500px;
  336. max-height: 500px;
  337. }
  338. }
  339. figure.unsquared {
  340. margin-bottom: 1.5rem;
  341. }
  342. figure.unsquared img {
  343. height: inherit;
  344. }
  345. @media print {
  346. body { font-size: 100%; }
  347. a:after { content: " (" attr(href) ")"; }
  348. a, a:link, a:visited, a:after {
  349. text-decoration: underline;
  350. text-shadow: none !important;
  351. background-image: none !important;
  352. background: white;
  353. color: black;
  354. }
  355. abbr[title] { border-bottom: 0; }
  356. abbr[title]:after { content: " (" attr(title) ")"; }
  357. img { page-break-inside: avoid; }
  358. @page { margin: 2cm .5cm; }
  359. h1, h2, h3 { page-break-after: avoid; }
  360. p3 { orphans: 3; widows: 3; }
  361. img {
  362. max-width: 250px !important;
  363. max-height: 250px !important;
  364. }
  365. nav, aside { display: none; }
  366. }
  367. ul.with_columns {
  368. column-count: 1;
  369. }
  370. @media (min-width: 20em) {
  371. ul.with_columns {
  372. column-count: 2;
  373. }
  374. }
  375. @media (min-width: 50em) {
  376. ul.with_columns {
  377. column-count: 3;
  378. }
  379. }
  380. ul.with_two_columns {
  381. column-count: 1;
  382. }
  383. @media (min-width: 20em) {
  384. ul.with_two_columns {
  385. column-count: 1;
  386. }
  387. }
  388. @media (min-width: 50em) {
  389. ul.with_two_columns {
  390. column-count: 2;
  391. }
  392. }
  393. .gallery {
  394. display: flex;
  395. flex-wrap: wrap;
  396. justify-content: space-around;
  397. }
  398. .gallery figure img {
  399. margin-left: 1rem;
  400. margin-right: 1rem;
  401. }
  402. .gallery figure figcaption {
  403. font-family: 'ConcourseT3'
  404. }
  405. footer {
  406. font-family: 'ConcourseT3';
  407. display: flex;
  408. flex-direction: column;
  409. border-top: 3px solid white;
  410. padding: 4rem 0;
  411. background-color: #07486c;
  412. color: white;
  413. }
  414. footer > * {
  415. max-width: 50rem;
  416. margin: 0 auto;
  417. }
  418. footer a {
  419. color: #f1c40f;
  420. }
  421. footer .avatar {
  422. width: 200px;
  423. height: 200px;
  424. border-radius: 50%;
  425. float: left;
  426. -webkit-shape-outside: circle();
  427. shape-outside: circle();
  428. margin-right: 2rem;
  429. padding: 2px 5px 5px 2px;
  430. background: white;
  431. border-left: 1px solid #f1c40f;
  432. border-top: 1px solid #f1c40f;
  433. border-right: 5px solid #f1c40f;
  434. border-bottom: 5px solid #f1c40f;
  435. }
  436. </style>
  437. <h1>
  438. <span><a id="jumper" href="#jumpto" title="Un peu perdu ?">?</a></span>
  439. Javascript - Event order (archive)
  440. <time>Pour la pérennité des contenus liés. Non-indexé, retrait sur simple email.</time>
  441. </h1>
  442. <section>
  443. <article>
  444. <h3><a href="http://www.quirksmode.org/js/events_order.html">Source originale du contenu</a></h3>
  445. <p class="intro">On the <a href="introevents.html">Introduction to events</a> page&#13;I asked a question that at first sight seems incomprehensible:&#13;“If an element and one of its ancestors have an event handler for the same event, which&#13;one should fire first?” Not surprisingly, this depends on the browser.</p>
  446. <p>&#13;&#13;<p>The basic problem is very simple. Suppose you have a element inside an element</p>
  447. <pre>
  448. -----------------------------------
  449. | element1 |
  450. | ------------------------- |
  451. | |element2 | |
  452. | ------------------------- |
  453. | |
  454. -----------------------------------
  455. </pre>&#13;&#13;<p>and both have an onClick event handler. If the user clicks on element2 he causes&#13;a click event in both element1 and element2. But which event fires first? Which event handler should&#13;be executed first? What, in other words, is the <em>event order</em>?</p>&#13;&#13;<h3>Two models</h3>&#13;&#13;<p>Not surprisingly, back in the bad old days Netscape and Microsoft came to different conclusions.</p>&#13;&#13;<ul><li>Netscape said that the event on element1 takes place first. This is called&#13;event <em>capturing</em>.</li>&#13;<li>Microsoft maintained that the event on element2 takes precedence. This is called&#13;event <em>bubbling</em>.</li>&#13;</ul>&#13;&#13;<p>The two event orders are radically opposed. Explorer&#13;only supports event bubbling. Mozilla, Opera 7 and Konqueror support both. Older Opera's and&#13;iCab support neither.</p>&#13;&#13;<h4>Event capturing</h4>&#13;&#13;<p>When you use event capturing</p>&#13;&#13;
  456. <pre>
  457. | |
  458. ---------------| |-----------------
  459. | element1 | | |
  460. | -----------| |----------- |
  461. | |element2 \ / | |
  462. | ------------------------- |
  463. | Event CAPTURING |
  464. -----------------------------------
  465. </pre>&#13;&#13;<p>the event handler of element1 fires first, the event handler of element2 fires last.</p>&#13;&#13;&#13;<h4>Event bubbling</h4>&#13;&#13;<p>When you use event bubbling</p>&#13;&#13;
  466. <pre>
  467. / \
  468. ---------------| |-----------------
  469. | element1 | | |
  470. | -----------| |----------- |
  471. | |element2 | | | |
  472. | ------------------------- |
  473. | Event BUBBLING |
  474. -----------------------------------
  475. </pre>&#13;&#13;<p>the event handler of element2 fires first, the event handler of element1 fires last.</p>&#13;&#13;<h3>W3C model</h3>&#13;&#13;<p>W3C has very sensibly decided to take a middle position in this struggle.&#13;Any event taking place in the&#13;<a href="http://www.w3.org/TR/2000/REC-DOM-Level-2-Events-20001113/" class="external">W3C event model</a> is first captured until it&#13;reaches the target element and then bubbles up again.</p>&#13;&#13;
  476. <pre>
  477. | | / \
  478. -----------------| |--| |-----------------
  479. | element1 | | | | |
  480. | -------------| |--| |----------- |
  481. | |element2 \ / | | | |
  482. | -------------------------------- |
  483. | W3C event model |
  484. ------------------------------------------
  485. </pre>&#13;&#13;<p>You, the web developer, can choose whether to register an event handler in the capturing or&#13;in the bubbling phase. This is done through the <code>addEventListener()</code>&#13;method explained on the <a href="events_advanced.html">Advanced models</a> page.&#13;If its last argument is <code>true</code> the event handler is set for the capturing phase, if it is&#13;<code>false</code> the event handler is set for the bubbling phase.</p>&#13;&#13;<p>Suppose you do</p>&#13;&#13;<pre>&#13;element1.addEventListener('click',doSomething2,true)&#13;element2.addEventListener('click',doSomething,false)&#13;</pre>&#13;&#13;<p>If the user clicks on element2 the following happens:</p>&#13;&#13;<ol>&#13;<li>The <code>click</code> event starts in the capturing phase. The event looks if any&#13;ancestor element of element2 has a <code>onclick</code> event handler for the capturing&#13;phase.</li>&#13;<li>The event finds one on element1. <code>doSomething2()</code> is&#13;executed.</li>&#13;<li>The event travels down to the target itself, no more event handlers for the capturing&#13;phase are found. The event moves to its bubbling phase and executes <code>doSomething()</code>,&#13;which is registered to element2 for the bubbling phase.</li>&#13;<li>The event travels upwards again and checks if any ancestor element of the&#13;target has an event handler for the bubbling phase. This is not the case, so nothing happens.</li>&#13;</ol>&#13;&#13;&#13;<p>The reverse would be</p>&#13;&#13;<pre>&#13;element1.addEventListener('click',doSomething2,false)&#13;element2.addEventListener('click',doSomething,false)&#13;</pre>&#13;&#13;<p>Now if the user clicks on element2 the following happens:</p>&#13;&#13;<ol>&#13;<li>The <code>click</code> event starts in the capturing phase. The event looks if any&#13;ancestor element of element2 has a <code>onclick</code> event handler for the capturing&#13;phase and doesn’t find any.</li>&#13;<li>The event travels down to the target itself.&#13;The event moves to its bubbling phase and executes <code>doSomething()</code>,&#13;which is registered to element2 for the bubbling phase.</li>&#13;<li>The event travels upwards again and checks if any ancestor element of the&#13;target has an event handler for the bubbling phase.</li>&#13;<li>The event finds one on element1. Now <code>doSomething2()</code> is executed.</li>&#13;</ol>&#13;&#13;<h4>Compatibility with traditional model</h4>&#13;&#13;<p>In the browsers that support the W3C DOM, a traditional event registration</p>&#13;&#13;<pre>&#13;element1.onclick = doSomething2;&#13;</pre>&#13;&#13;<p>is seen as a registration in the <em>bubbling phase</em>.</p>&#13;&#13;&#13;<h3>Use of event bubbling</h3>&#13;&#13;<p>Few web developers consciously use event capturing or bubbling. In Web pages as they are made&#13;today, it is simply not necessary to let a bubbling event be handled by several different event handlers.&#13;Users might get confused by several things happening after one mouse click, and usually you want&#13;to keep your event handling scripts separated. When the user clicks on an element, something happens,&#13;when he clicks on another element, something else happens.</p>&#13;&#13;<p>Of course this might change in the future, and it’s good to have models available that&#13;are forward compatible. But the main practical use of event capturing and bubbling today&#13;is the registration of default functions.</p>&#13;&#13;<h3>It always happens</h3>&#13;&#13;<p>What you first need to understand is that event capturing or bubbling always happens.&#13;If you define a general onclick event handler for your entire document</p>&#13;&#13;<pre>&#13;document.onclick = doSomething;&#13;if (document.captureEvents) document.captureEvents(Event.CLICK);&#13;</pre>&#13;&#13;<p>any <code>click</code> event on any element in the document will eventually bubble up to the document and&#13;thus fire this general event handler.&#13;Only when a previous event handling script explicitly orders the event to stop bubbling, it will not propagate to the&#13;document.</p>&#13;&#13;<h3>Uses</h3>&#13;&#13;<p>Because any event ends up on the document, default event handlers become possible.&#13;Suppose you have this page:</p>&#13;&#13;
  486. <pre>
  487. ------------------------------------
  488. | document |
  489. | --------------- ------------ |
  490. | | element1 | | element2 | |
  491. | --------------- ------------ |
  492. | |
  493. ------------------------------------</p>
  494. <pre><code>element1.onclick = doSomething;
  495. element2.onclick = doSomething;
  496. document.onclick = defaultFunction;
  497. </code></pre>
  498. <p></pre>
  499. &#13;<p>Now if the user clicks on element1 or 2, <code>doSomething()</code> is executed. You can&#13;stop the event propagation here, if you wish. If you don’t the event bubbles up to&#13;<code>defaultFunction()</code>.&#13;If the user clicks anywhere else <code>defaultFunction()</code> is also executed. This might be&#13;useful sometimes.</p>&#13;&#13;&#13;<p>Setting document–wide event handlers is necessary in drag–and–drop&#13;scripts. Typically a <code>mousedown</code> event on a layer selects this layer and makes&#13;it respond to the <code>mousemove</code> event. Though the&#13;<code>mousedown</code> is usually registered on the layer to avoid browser bugs, both&#13;other event handlers must be document–wide.</p>&#13;&#13;<p>Remember the First Law of Browserology: anything can happen, and it usually does when you’re&#13;least prepared for it. So it may happen that the user moves his mouse very wildly and the&#13;script doesn’t keep up so that the mouse is not over the layer any more.</p>&#13;&#13;<ul>&#13;<li>If the <code>onmousemove</code> event handler is registered to the layer,&#13;the layer doesn’t react to the mouse movement any more, causing confusion.</li>&#13;&#13;<li>If the <code>onmouseup</code> event handler is registered on the layer,&#13;this event isn’t caught either so that the layer keeps reacting to the mouse&#13;movements even after the user thinks he dropped the layer. This causes even more confusion.</li>&#13;</ul>&#13;&#13;<p>So in this case event bubbling is very useful because registering&#13;your event handlers on document level makes sure they’re always executed.</p>&#13;&#13;<h3>Turning it off</h3>&#13;&#13;<p>But usually you want to turn all capturing and bubbling off to keep functions from&#13;interfering with each other.&#13;Besides, if your document structure is very complex (lots of nested tables and such) you may save system&#13;resources by turning off bubbling. The browser has to go through every single ancestor element&#13;of the event target to see if it has an event handler. Even if none are found, the search still takes time.</p>&#13;&#13;<p>In the Microsoft model you must set the event’s <code>cancelBubble</code> property to true.</p>&#13;&#13;<pre>&#13;window.event.cancelBubble = true&#13;</pre>&#13;&#13;<p>In the W3C model you must call the event’s <code>stopPropagation()</code> method. </p>&#13;&#13;<pre>&#13;e.stopPropagation()&#13;</pre>&#13;&#13;<p>This stops all propagation of the event in the bubbling phase. For a complete cross-browser experience do</p>&#13;&#13;<pre>&#13;function doSomething(e)&#13;{&#13; if (!e) var e = window.event;&#13; e.cancelBubble = true;&#13; if (e.stopPropagation) e.stopPropagation();&#13;}&#13;</pre>&#13;&#13;<p class="smaller">Setting the <code>cancelBubble</code> property in browsers that don’t support it doesn’t hurt.&#13;The browser shrugs and creates the property. Of course it doesn’t actually&#13;cancel the bubbling, but the assignment itself is safe.</p>&#13;&#13;<h3>currentTarget</h3>&#13;&#13;<p>As we’ve seen earlier, an event has a <code>target</code> or <code>srcElement</code> that&#13;contains a reference to the element the event happened on. In our example this is element2,&#13;since the user clicked on it.</p>&#13;&#13;<p>It is very important to understand that during the capturing and bubbling phases (if any)&#13;this target does not change: it always remains a reference to element2.</p>&#13;&#13;<p>But suppose we register these event handlers:</p>&#13;&#13;<pre>&#13;element1.onclick = doSomething;&#13;element2.onclick = doSomething;&#13;</pre>&#13;&#13;<p>If the user clicks on element2 <code>doSomething()</code> is executed twice. But how&#13;do you know which HTML element is currently handling the event? <code>target/srcElement</code>&#13;don’t give a clue, they always refer to element2 since it is the original source of the&#13;event.</p>&#13;&#13;<p>To solve this problem W3C has added the <code>currentTarget</code> property. It contains a&#13;reference to the HTML element the event is currently being handled by: exactly what we need.&#13;Unfortunately the Microsoft model doesn’t contain a similar property.</p>&#13;&#13;<p>You can also use&#13;<a href="this.html">the <code>this</code> keyword</a>.&#13;In the example above it refers to the HTML element the event is handled on, just like&#13;<code>currentTarget</code>.</p>&#13;&#13;<h3>Problems of the Microsoft model</h3>&#13;&#13;<p>But when you use the Microsoft event registration model&#13;the <code>this</code> keyword doesn’t refer to the HTML element. Combined with the&#13;lack of a <code>currentTarget</code>–like property in the Microsoft model,&#13;this means that if you do</p>&#13;&#13;<pre>&#13;element1.attachEvent('onclick',doSomething)&#13;element2.attachEvent('onclick',doSomething)&#13;</pre>&#13;&#13;<p>you <em>cannot</em> know which HTML element currently handles the event. This is the most&#13;serious problem with the Microsoft event registration model and for me it’s reason enough&#13;never to use it, not even in IE/Win only applications.</p>&#13;&#13;<p>I hope Microsoft will soon add a <code>currentTarget</code>–like property — or maybe&#13;even follow the standard? Web developers need this information.</p>&#13;&#13;<h3>Continue</h3>&#13;&#13;<p>If you wish to go through all event pages in order, you should now continue with the&#13;<a href="events_mouse.html">Mouse events</a> page.</p></p>
  500. </article>
  501. </section>
  502. <nav id="jumpto">
  503. <p>
  504. <a href="/david/blog/">Accueil du blog</a> |
  505. <a href="http://www.quirksmode.org/js/events_order.html">Source originale</a> |
  506. <a href="/david/stream/2019/">Accueil du flux</a>
  507. </p>
  508. </nav>
  509. <footer>
  510. <div>
  511. <img src="/static/david/david-larlet-avatar.jpg" loading="lazy" class="avatar" width="200" height="200">
  512. <p>
  513. Bonjour/Hi!
  514. Je suis <a href="/david/" title="Profil public">David&nbsp;Larlet</a>, je vis actuellement à Montréal et j’alimente cet espace depuis 15 ans. <br>
  515. Si tu as apprécié cette lecture, n’hésite pas à poursuivre ton exploration. Par exemple via les <a href="/david/blog/" title="Expériences bienveillantes">réflexions bimestrielles</a>, la <a href="/david/stream/2019/" title="Pensées (dés)articulées">veille hebdomadaire</a> ou en t’abonnant au <a href="/david/log/" title="S’abonner aux publications via RSS">flux RSS</a> (<a href="/david/blog/2019/flux-rss/" title="Tiens c’est quoi un flux RSS ?">so 2005</a>).
  516. </p>
  517. <p>
  518. Je m’intéresse à la place que je peux avoir dans ce monde. En tant qu’humain, en tant que membre d’une famille et en tant qu’associé d’une coopérative. De temps en temps, je fais aussi des <a href="https://github.com/davidbgk" title="Principalement sur Github mais aussi ailleurs">trucs techniques</a>. Et encore plus rarement, <a href="/david/talks/" title="En ce moment je laisse plutôt la place aux autres">j’en parle</a>.
  519. </p>
  520. <p>
  521. Voici quelques articles choisis :
  522. <a href="/david/blog/2019/faire-equipe/" title="Accéder à l’article complet">Faire équipe</a>,
  523. <a href="/david/blog/2018/bivouac-automnal/" title="Accéder à l’article complet">Bivouac automnal</a>,
  524. <a href="/david/blog/2018/commodite-effondrement/" title="Accéder à l’article complet">Commodité et effondrement</a>,
  525. <a href="/david/blog/2017/donnees-communs/" title="Accéder à l’article complet">Des données aux communs</a>,
  526. <a href="/david/blog/2016/accompagner-enfant/" title="Accéder à l’article complet">Accompagner un enfant</a>,
  527. <a href="/david/blog/2016/senior-developer/" title="Accéder à l’article complet">Senior developer</a>,
  528. <a href="/david/blog/2016/illusion-sociale/" title="Accéder à l’article complet">L’illusion sociale</a>,
  529. <a href="/david/blog/2016/instantane-scopyleft/" title="Accéder à l’article complet">Instantané Scopyleft</a>,
  530. <a href="/david/blog/2016/enseigner-web/" title="Accéder à l’article complet">Enseigner le Web</a>,
  531. <a href="/david/blog/2016/simplicite-defaut/" title="Accéder à l’article complet">Simplicité par défaut</a>,
  532. <a href="/david/blog/2016/minimalisme-esthetique/" title="Accéder à l’article complet">Minimalisme et esthétique</a>,
  533. <a href="/david/blog/2014/un-web-omni-present/" title="Accéder à l’article complet">Un web omni-présent</a>,
  534. <a href="/david/blog/2014/manifeste-developpeur/" title="Accéder à l’article complet">Manifeste de développeur</a>,
  535. <a href="/david/blog/2013/confort-convivialite/" title="Accéder à l’article complet">Confort et convivialité</a>,
  536. <a href="/david/blog/2013/testament-numerique/" title="Accéder à l’article complet">Testament numérique</a>,
  537. et <a href="/david/blog/" title="Accéder aux archives">bien d’autres…</a>
  538. </p>
  539. <p>
  540. On peut <a href="mailto:david%40larlet.fr" title="Envoyer un courriel">échanger par courriel</a>. Si éventuellement tu souhaites que l’on travaille ensemble, tu devrais commencer par consulter le <a href="http://larlet.com">profil dédié à mon activité professionnelle</a> et/ou contacter directement <a href="http://scopyleft.fr/">scopyleft</a>, la <abbr title="Société coopérative et participative">SCOP</abbr> dont je fais partie depuis six ans. Je recommande au préalable de lire <a href="/david/blog/2018/cout-site/" title="Attention ce qui va suivre peut vous choquer">combien coûte un site</a> et pourquoi je suis plutôt favorable à une <a href="/david/pro/devis/" title="Discutons-en !">non-demande de devis</a>.
  541. </p>
  542. <p>
  543. Je ne traque pas ta navigation mais mon
  544. <abbr title="Alwaysdata, 62 rue Tiquetonne 75002 Paris, +33.184162340">hébergeur</abbr>
  545. conserve des logs d’accès.
  546. </p>
  547. </div>
  548. </footer>
  549. <script type="text/javascript">
  550. ;(_ => {
  551. const jumper = document.getElementById('jumper')
  552. jumper.addEventListener('click', e => {
  553. e.preventDefault()
  554. const anchor = e.target.getAttribute('href')
  555. const targetEl = document.getElementById(anchor.substring(1))
  556. targetEl.scrollIntoView({behavior: 'smooth'})
  557. })
  558. })()
  559. </script>