tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

events-suite-manual.html (25139B)


      1 <!DOCTYPE html>
      2 <title>drag &amp; drop - event sequence for draggable elements</title>
      3 <script type="text/javascript" src="/resources/testharness.js"></script>
      4 <script type="text/javascript" src="/resources/testharnessreport.js"></script>
      5 <style type="text/css">
      6  /* use margins instead of padding to make sure the body begins at the top of the page */
      7  html, body {
      8    margin: 0;
      9  }
     10  body {
     11    padding: 116px 8px 8px;
     12  }
     13  #testhere div {
     14    height: 100px;
     15    width: 100px;
     16    position: absolute;
     17    top: 8px;
     18  }
     19  #orange {
     20    background-color: orange;
     21    left: 8px;
     22  }
     23  #fuchsia {
     24    background-color: fuchsia;
     25    left: 158px;
     26  }
     27  #yellow {
     28    background-color: yellow;
     29    left: 308px;
     30  }
     31  #blue {
     32    background-color: navy;
     33    left: 458px;
     34  }
     35 </style>
     36 
     37 <script>
     38 setup(function () {},{explicit_done:true,explicit_timeout:true});
     39 window.onload = function () {
     40  var orange = document.querySelector('#orange')
     41  var fuchsia = document.querySelector('#fuchsia')
     42  var yellow = document.querySelector('#yellow')
     43  var blue = document.querySelector('#blue')
     44  var body = document.body;
     45 
     46  var events = new Array
     47 
     48  orange.ondragstart = function (e) {
     49    events.push('orange.ondragstart');
     50    e.dataTransfer.effectAllowed = 'copy';
     51    e.dataTransfer.setData('Text', 'foo');
     52  };
     53  orange.ondrag = function () { events.push('orange.ondrag'); };
     54  orange.ondragenter = function () { events.push('orange.ondragenter'); };
     55  orange.ondragover = function () { events.push('orange.ondragover'); };
     56  orange.ondragleave = function () { events.push('orange.ondragleave'); };
     57  orange.ondrop = function () { events.push('orange.ondrop'); return false; };
     58  orange.ondragend = function () { events.push('orange.ondragend'); };
     59  orange.onmousedown = function () { events.push('orange.onmousedown'); };
     60  orange.onmouseup = function () { events.push('orange.onmouseup'); };
     61 
     62  /* Events for the fuchsia box */
     63  fuchsia.ondragstart = function () { events.push('pink.ondragstart'); };
     64  fuchsia.ondrag = function () { events.push('pink.ondrag'); };
     65  fuchsia.ondragenter = function () { events.push('pink.ondragenter'); };
     66  fuchsia.ondragover = function () { events.push('pink.ondragover'); };
     67  fuchsia.ondragleave = function () { events.push('pink.ondragleave'); };
     68  fuchsia.ondrop = function () { events.push('pink.ondrop'); return false; };
     69  fuchsia.ondragend = function () { events.push('pink.ondragend'); };
     70  fuchsia.onmousedown = function () { events.push('pink.onmousedown'); };
     71  fuchsia.onmouseup = function () { events.push('pink.onmouseup'); };
     72 
     73  /* Events for the fuchsia box */
     74  yellow.ondragstart = function () { events.push('yellow.ondragstart'); };
     75  yellow.ondrag = function () { events.push('yellow.ondrag'); };
     76  yellow.ondragenter = function () { events.push('yellow.ondragenter'); return false; };
     77  yellow.ondragover = function () { events.push('yellow.ondragover'); return false; };
     78  yellow.ondragleave = function () { events.push('yellow.ondragleave'); };
     79  yellow.ondrop = function () { events.push('yellow.ondrop'); return false; };
     80  yellow.ondragend = function () { events.push('yellow.ondragend'); };
     81  yellow.onmousedown = function () { events.push('yellow.onmousedown'); };
     82  yellow.onmouseup = function () { events.push('yellow.onmouseup'); };
     83 
     84  /* Events for the blue box (droppable) */
     85  blue.ondragstart = function () { events.push('blue.ondragstart'); };
     86  blue.ondrag = function () { events.push('blue.ondrag'); };
     87  blue.ondragenter = function () { events.push('blue.ondragenter'); return false; };
     88  blue.ondragover = function () { events.push('blue.ondragover'); return false; };
     89  blue.ondragleave = function () { events.push('blue.ondragleave'); };
     90  blue.ondrop = function () { events.push('blue.ondrop'); return false; };
     91  blue.ondragend = function () { events.push('blue.ondragend'); };
     92  blue.onmousedown = function () { events.push('blue.onmousedown'); };
     93  blue.onmouseup = function () { events.push('blue.onmouseup'); };
     94 
     95  /* Events for the page body */
     96  body.ondragstart = function (e) { events.push( ( e.target == body ) ? 'body.ondragstart': 'bubble.ondragstart' ); };
     97  body.ondrag = function (e) { events.push( ( e.target == body ) ? 'body.ondrag': 'bubble.ondrag' ); };
     98  body.ondragenter = function (e) { events.push( ( e.target == body ) ? 'body.ondragenter': 'bubble.ondragenter' ); };
     99  body.ondragover = function (e) { events.push( ( e.target == body ) ? 'body.ondragover': 'bubble.ondragover' ); };
    100  body.ondragleave = function (e) { events.push( ( e.target == body ) ? 'body.ondragleave': 'bubble.ondragleave' ); };
    101  body.ondrop = function (e) { events.push( ( e.target == body ) ? 'body.ondrop': 'bubble.ondrop' ); };
    102  body.ondragend = function (e) { events.push( ( e.target == body ) ? 'body.ondragend': 'bubble.ondragend' ); setTimeout(finish,100); };
    103  body.onmousedown = function (e) { events.push( ( e.target == body ) ? 'body.onmousedown': 'bubble.onmousedown' ); };
    104  body.onmouseup = function (e) { events.push( ( e.target == body ) ? 'body.onmouseup': 'bubble.onmouseup' ); };
    105 
    106  function finish(e) {
    107    var i, evindex;
    108    events = events.join('-');
    109    /*
    110      Normalise; reduce repeating event sequences to only 2 occurrences.
    111      This makes the final event sequence predictable, no matter how many times the drag->dragover sequences repeat.
    112      Two occurrances are kept in each case to allow testing to make sure the sequence really is repeating.
    113    */
    114    //spec compliant - div dragenter is not cancelled, so body dragenter fires and body becomes current target
    115    //repeats while drag is over orange or fuchsia or the body
    116    events = events.replace(/(-orange\.ondrag-bubble\.ondrag-body\.ondragover){3,}/g,'$1$1');
    117    //repeats while dragging over yellow
    118    events = events.replace(/(-orange\.ondrag-bubble\.ondrag-yellow\.ondragover-bubble\.ondragover){3,}/g,'$1$1');
    119    //repeats while dragging over blue
    120    events = events.replace(/(-orange\.ondrag-bubble\.ondrag-blue\.ondragover-bubble\.ondragover){3,}/g,'$1$1');
    121    //non-spec-compliant repeats while dragging over orange
    122    events = events.replace(/(-orange\.ondrag-bubble\.ondrag-orange\.ondragover-bubble\.ondragover){3,}/g,'$1$1');
    123    //non-spec-compliant repeats while dragging over fuchsia
    124    events = events.replace(/(-orange\.ondrag-bubble\.ondrag-pink\.ondragover-bubble\.ondragover){3,}/g,'$1$1');
    125    events = events.split(/-/g);
    126 
    127    test(function () {
    128      assert_array_equals(events,
    129 
    130      [/*  1 */ 'orange.onmousedown', //mouse down
    131        /*  2 */ 'bubble.onmousedown',
    132 
    133        /*  3 */ 'orange.ondragstart', //dragging begins
    134        /*  4 */ 'bubble.ondragstart',
    135 
    136        /*  5 */ 'orange.ondrag',      //mouse is over orange
    137        /*  6 */ 'bubble.ondrag',
    138        /*  7 */ 'orange.ondragenter', //not cancelled
    139        /*  8 */ 'bubble.ondragenter',
    140        /*  9 */ 'body.ondragenter',   //so body becomes current target, and the event fires there as well
    141        /* 10 */ 'body.ondragover',
    142 
    143        /* 11 */ 'orange.ondrag',      //start repeating (some over orange, some over body)
    144        /* 12 */ 'bubble.ondrag',
    145        /* 13 */ 'body.ondragover',
    146        /* 14 */ 'orange.ondrag',      //...twice to make sure it actually repeats
    147        /* 15 */ 'bubble.ondrag',
    148        /* 16 */ 'body.ondragover',    //end repeating
    149 
    150        /* 17 */ 'orange.ondrag',      //mouse moves over pink
    151        /* 18 */ 'bubble.ondrag',
    152        /* 19 */ 'pink.ondragenter',   //not cancelled
    153        /* 20 */ 'bubble.ondragenter',
    154        /* 21 */ 'body.ondragover',    //so body becomes current target, but since it was already the target, dragenter does not need to fire again
    155 
    156        /* 22 */ 'orange.ondrag',      //start repeating (some over pink, some over body)
    157        /* 23 */ 'bubble.ondrag',
    158        /* 24 */ 'body.ondragover',
    159        /* 25 */ 'orange.ondrag',      //...twice to make sure it actually repeats
    160        /* 26 */ 'bubble.ondrag',
    161        /* 27 */ 'body.ondragover',    //end repeating
    162 
    163        /* 28 */ 'orange.ondrag',      //mouse moves over yellow
    164        /* 29 */ 'bubble.ondrag',
    165        /* 30 */ 'yellow.ondragenter',
    166        /* 31 */ 'bubble.ondragenter',
    167        /* 32 */ 'body.ondragleave',
    168        /* 33 */ 'yellow.ondragover',
    169        /* 34 */ 'bubble.ondragover',
    170 
    171        /* 35 */ 'orange.ondrag',      //start repeating (over yellow)
    172        /* 36 */ 'bubble.ondrag',
    173        /* 37 */ 'yellow.ondragover',
    174        /* 38 */ 'bubble.ondragover',
    175        /* 39 */ 'orange.ondrag',      //...twice to make sure it actually repeats
    176        /* 40 */ 'bubble.ondrag',
    177        /* 41 */ 'yellow.ondragover',
    178        /* 42 */ 'bubble.ondragover',  //end repeating
    179 
    180        /* 43 */ 'orange.ondrag',      //mouse moves over body
    181        /* 44 */ 'bubble.ondrag',
    182        /* 45 */ 'body.ondragenter',   //not cancelled
    183        /* 46 */ 'body.ondragenter',   //so it fires again and sets body as current target
    184        /* 47 */ 'yellow.ondragleave',
    185        /* 48 */ 'bubble.ondragleave',
    186        /* 49 */ 'body.ondragover',
    187 
    188        /* 50 */ 'orange.ondrag',      //start repeating (over body)
    189        /* 51 */ 'bubble.ondrag',
    190        /* 52 */ 'body.ondragover',
    191        /* 53 */ 'orange.ondrag',      //...twice to make sure it actually repeats
    192        /* 54 */ 'bubble.ondrag',
    193        /* 55 */ 'body.ondragover',    //end repeating
    194 
    195        /* 56 */ 'orange.ondrag',      //mouse moves over blue
    196        /* 57 */ 'bubble.ondrag',
    197        /* 58 */ 'blue.ondragenter',
    198        /* 59 */ 'bubble.ondragenter',
    199        /* 60 */ 'body.ondragleave',
    200        /* 61 */ 'blue.ondragover',
    201        /* 62 */ 'bubble.ondragover',
    202 
    203        /* 63 */ 'orange.ondrag',      //start repeating (over blue)
    204        /* 64 */ 'bubble.ondrag',
    205        /* 65 */ 'blue.ondragover',
    206        /* 66 */ 'bubble.ondragover',
    207        /* 67 */ 'orange.ondrag',      //...twice to make sure it actually repeats
    208        /* 68 */ 'bubble.ondrag',
    209        /* 69 */ 'blue.ondragover',
    210        /* 70 */ 'bubble.ondragover',  //end repeating
    211 
    212        /* 71 */ 'blue.ondrop',        //release
    213        /* 72 */ 'bubble.ondrop',
    214        /* 73 */ 'orange.ondragend',
    215        /* 74 */ 'bubble.ondragend']
    216 
    217      );
    218    }, 'Overall sequence');
    219 
    220    /* ondragstart */
    221    test(function () { assert_true( events.indexOf('orange.ondragstart') != -1 ); }, "orange.ondragstart should fire");
    222    test(function () { assert_equals( events.filter(function (e) { if (e == 'orange.ondragstart') return e; }).length, 1); }, "orange.ondragstart should fire 1 time");
    223    test(function () { assert_equals( events[2], 'orange.ondragstart' ); }, "orange.ondragstart should be event handler #3");
    224    test(function () { assert_equals( events.indexOf('pink.ondragstart'), -1 ); }, "pink.ondragstart should not fire");
    225    test(function () { assert_equals( events.indexOf('yellow.ondragstart'), -1 ); }, "yellow.ondragstart should not fire");
    226    test(function () { assert_equals( events.indexOf('blue.ondragstart'), -1 ); }, "blue.ondragstart should not fire");
    227    test(function () { assert_equals( events.indexOf('body.ondragstart'), -1 ); }, "ondragstart should not fire at the body");
    228    test(function () { assert_true( events.indexOf('bubble.ondragstart') != -1 ); }, "ondragstart should bubble to body");
    229    test(function () { assert_equals( events.filter(function (e) { if (e == 'bubble.ondragstart') return e; }).length, 1); }, "ondragstart should only bubble to body 1 time");
    230    test(function () { assert_equals( events[3], 'bubble.ondragstart' ); }, "ondragstart should bubble to body as event handler #4");
    231 
    232    /* ondrag */
    233    test(function () { assert_true( events.indexOf('orange.ondrag') != -1 ); }, "orange.ondrag should fire");
    234    test(function () { assert_equals( events.filter(function (e) { if (e == 'orange.ondrag') return e; }).length, 15); }, "orange.ondrag should fire 15 times");
    235    for( var i = 0, evindex = [4,10,13,16,21,24,27,34,38,42,49,52,55,62,66]; i < evindex.length; i++ ) {
    236      test(function () { assert_equals( events[evindex[i]], 'orange.ondrag' ); }, "orange.ondrag should be event handler #"+(evindex[i]+1));
    237    }
    238    test(function () { assert_equals( events.indexOf('pink.ondrag'), -1 ); }, "pink.ondrag should not fire");
    239    test(function () { assert_equals( events.indexOf('yellow.ondrag'), -1 ); }, "yellow.ondrag should not fire");
    240    test(function () { assert_equals( events.indexOf('blue.ondrag'), -1 ); }, "blue.ondrag should not fire");
    241    test(function () { assert_equals( events.indexOf('body.ondrag'), -1 ); }, "ondrag should not fire at the body");
    242    test(function () { assert_true( events.indexOf('bubble.ondrag') != -1 ); }, "ondrag should bubble to body");
    243    test(function () { assert_equals( events.filter(function (e) { if (e == 'bubble.ondrag') return e; }).length, 15); }, "ondrag should bubble to body 15 times");
    244    for( var i = 0, evindex = [5,11,14,17,22,25,28,35,39,43,50,53,56,63,67]; i < evindex.length; i++ ) {
    245      test(function () { assert_equals( events[evindex[i]], 'bubble.ondrag' ); }, "ondrag should bubble to body as event handler #"+(evindex[i]+1));
    246    }
    247 
    248    /* ondragenter */
    249    test(function () { assert_true( events.indexOf('orange.ondragenter') != -1 ); }, "orange.ondragenter should fire");
    250    test(function () { assert_equals( events.filter(function (e) { if (e == 'orange.ondragenter') return e; }).length, 1); }, "orange.ondragenter should fire 1 time");
    251    test(function () { assert_equals( events[6], 'orange.ondragenter' ); }, "orange.ondragenter should be event handler #7");
    252    test(function () { assert_true( events.indexOf('pink.ondragenter') != -1 ); }, "pink.ondragenter should fire");
    253    test(function () { assert_equals( events.filter(function (e) { if (e == 'pink.ondragenter') return e; }).length, 1); }, "pink.ondragenter should fire 1 time");
    254    test(function () { assert_equals( events[18], 'pink.ondragenter' ); }, "pink.ondragenter should be event handler #19");
    255    test(function () { assert_true( events.indexOf('yellow.ondragenter') != -1 ); }, "yellow.ondragenter should fire");
    256    test(function () { assert_equals( events.filter(function (e) { if (e == 'yellow.ondragenter') return e; }).length, 1); }, "yellow.ondragenter should fire 1 time");
    257    test(function () { assert_equals( events[29], 'yellow.ondragenter' ); }, "yellow.ondragenter should be event handler #30");
    258    test(function () { assert_true( events.indexOf('blue.ondragenter') != -1 ); }, "blue.ondragenter should fire");
    259    test(function () { assert_equals( events.filter(function (e) { if (e == 'blue.ondragenter') return e; }).length, 1); }, "blue.ondragenter should fire 1 time");
    260    test(function () { assert_equals( events[57], 'blue.ondragenter' ); }, "blue.ondragenter should be event handler #58");
    261    test(function () { assert_true( events.indexOf('body.ondragenter') != -1 ); }, "ondragenter should fire at body");
    262    test(function () { assert_equals( events.filter(function (e) { if (e == 'body.ondragenter') return e; }).length, 3); }, "ondragenter should fire at body 2 times");
    263    for( var i = 0, evindex = [8,44,45]; i < evindex.length; i++ ) {
    264      test(function () { assert_equals( events[evindex[i]], 'body.ondragenter' ); }, "ondragenter should fire at body as event handler #"+(evindex[i]+1));
    265    }
    266    test(function () { assert_true( events.indexOf('bubble.ondragenter') != -1 ); }, "ondragenter should bubble to body");
    267    test(function () { assert_equals( events.filter(function (e) { if (e == 'bubble.ondragenter') return e; }).length, 4); }, "ondragenter should bubble to body 4 times");
    268    for( var i = 0, evindex = [7,19,30,58]; i < evindex.length; i++ ) {
    269      test(function () { assert_equals( events[evindex[i]], 'bubble.ondragenter' ); }, "ondragenter should bubble to body as event handler #"+(evindex[i]+1));
    270    }
    271 
    272    /* ondragover */
    273    test(function () { assert_equals( events.indexOf('orange.ondragover'), -1 ); }, "orange.ondragover should not fire");
    274    test(function () { assert_equals( events.indexOf('pink.ondragover'), -1 ); }, "pink.ondragover should not fire");
    275    test(function () { assert_true( events.indexOf('yellow.ondragover') != -1 ); }, "yellow.ondragover should fire");
    276    test(function () { assert_equals( events.filter(function (e) { if (e == 'yellow.ondragover') return e; }).length, 3); }, "yellow.ondragover should fire 3 times");
    277    for( var i = 0, evindex = [32,36,40]; i < evindex.length; i++ ) {
    278      test(function () { assert_equals( events[evindex[i]], 'yellow.ondragover' ); }, "yellow.ondragover should be event handler #"+(evindex[i]+1));
    279    }
    280    test(function () { assert_true( events.indexOf('blue.ondragover') != -1 ); }, "blue.ondragover should fire");
    281    test(function () { assert_equals( events.filter(function (e) { if (e == 'blue.ondragover') return e; }).length, 3); }, "blue.ondragover should fire 9 times");
    282    for( var i = 0, evindex = [60,64,68]; i < evindex.length; i++ ) {
    283      test(function () { assert_equals( events[evindex[i]], 'blue.ondragover' ); }, "blue.ondragover should be event handler #"+(evindex[i]+1));
    284    }
    285    test(function () { assert_true( events.indexOf('body.ondragover') != -1 ); }, "ondragover should fire at body");
    286    test(function () { assert_equals( events.filter(function (e) { if (e == 'body.ondragover') return e; }).length, 9); }, "ondragover should fire at body 2 times");
    287    for( var i = 0, evindex = [9,12,15,20,23,26,48,51,54]; i < evindex.length; i++ ) {
    288      test(function () { assert_equals( events[evindex[i]], 'body.ondragover' ); }, "ondragover should fire at body as event handler #"+(evindex[i]+1));
    289    }
    290    test(function () { assert_true( events.indexOf('bubble.ondragover') != -1 ); }, "ondragover should bubble to body");
    291    test(function () { assert_equals( events.filter(function (e) { if (e == 'bubble.ondragover') return e; }).length, 6); }, "ondragover should bubble to body 6 times");
    292    for( var i = 0, evindex = [33,37,41,61,65,69]; i < evindex.length; i++ ) {
    293      test(function () { assert_equals( events[evindex[i]], 'bubble.ondragover' ); }, "ondragover should bubble to body as event handler #"+(evindex[i]+1));
    294    }
    295 
    296    /* ondragleave */
    297    test(function () { assert_equals( events.indexOf('orange.ondragleave'), -1 ); }, "orange.ondragleave should not fire");
    298    test(function () { assert_equals( events.indexOf('pink.ondragleave'), -1 ); }, "pink.ondragleave should not fire");
    299    test(function () { assert_true( events.indexOf('yellow.ondragleave') != -1 ); }, "yellow.ondragleave should fire");
    300    test(function () { assert_equals( events.filter(function (e) { if (e == 'yellow.ondragleave') return e; }).length, 1); }, "yellow.ondragleave should fire 1 time");
    301    test(function () { assert_equals( events[46], 'yellow.ondragleave' ); }, "yellow.ondragleave should be event handler #47");
    302    test(function () { assert_equals( events.indexOf('blue.ondragleave'), -1 ); }, "blue.ondragleave should not fire");
    303    test(function () { assert_true( events.indexOf('body.ondragleave') != -1 ); }, "ondragleave should fire at body");
    304    test(function () { assert_equals( events.filter(function (e) { if (e == 'body.ondragleave') return e; }).length, 2); }, "ondragleave should fire at body 2 times");
    305    for( var i = 0, evindex = [31,59]; i < evindex.length; i++ ) {
    306      test(function () { assert_equals( events[evindex[i]], 'body.ondragleave' ); }, "ondragleave should fire at body as event handler #"+(evindex[i]+1));
    307    }
    308    test(function () { assert_true( events.indexOf('bubble.ondragleave') != -1 ); }, "ondragleave should bubble to body");
    309    test(function () { assert_equals( events.filter(function (e) { if (e == 'bubble.ondragleave') return e; }).length, 1); }, "ondragleave should bubble to body 1 time");
    310    test(function () { assert_equals( events[47], 'bubble.ondragleave' ); }, "ondragleave should bubble to body as event handler #48");
    311 
    312    /* ondrop */
    313    test(function () { assert_equals( events.indexOf('orange.ondrop'), -1 ); }, "orange.ondrop should not fire");
    314    test(function () { assert_equals( events.indexOf('pink.ondrop'), -1 ); }, "pink.ondrop should not fire");
    315    test(function () { assert_equals( events.indexOf('yellow.ondrop'), -1 ); }, "yellow.ondrop should not fire");
    316    test(function () { assert_true( events.indexOf('blue.ondrop') != -1 ); }, "blue.ondrop should fire");
    317    test(function () { assert_equals( events.filter(function (e) { if (e == 'blue.ondrop') return e; }).length, 1); }, "blue.ondrop should fire 1 time");
    318    test(function () { assert_equals( events[70], 'blue.ondrop' ); }, "blue.ondrop should be event handler #71");
    319    test(function () { assert_equals( events.indexOf('body.ondrop'), -1 ); }, "ondrop should not fire at body");
    320    test(function () { assert_true( events.indexOf('bubble.ondrop') != -1 ); }, "ondrop should bubble to body");
    321    test(function () { assert_equals( events.filter(function (e) { if (e == 'bubble.ondrop') return e; }).length, 1); }, "ondrop should bubble to body 1 time");
    322    test(function () { assert_equals( events[71], 'bubble.ondrop' ); }, "ondrop should bubble to body as event handler #72");
    323 
    324    /* ondragend */
    325    test(function () { assert_true( events.indexOf('orange.ondragend') != -1 ); }, "orange.ondragend should fire");
    326    test(function () { assert_equals( events.filter(function (e) { if (e == 'orange.ondragend') return e; }).length, 1); }, "orange.ondragend should fire 1 time");
    327    test(function () { assert_equals( events[72], 'orange.ondragend' ); }, "orange.ondragend should be event handler #73");
    328    test(function () { assert_equals( events.indexOf('pink.ondragend'), -1 ); }, "pink.ondragend should not fire");
    329    test(function () { assert_equals( events.indexOf('yellow.ondragend'), -1 ); }, "yellow.ondragend should not fire");
    330    test(function () { assert_equals( events.indexOf('blue.ondragend'), -1 ); }, "blue.ondragend should not fire");
    331    test(function () { assert_equals( events.indexOf('body.ondragend'), -1 ); }, "ondragend should not fire at body");
    332    test(function () { assert_true( events.indexOf('bubble.ondragend') != -1 ); }, "ondragend should bubble to body");
    333    test(function () { assert_equals( events.filter(function (e) { if (e == 'bubble.ondragend') return e; }).length, 1); }, "ondragend should bubble to body 1 time");
    334    test(function () { assert_equals( events[73], 'bubble.ondragend' ); }, "ondragend should bubble to body as event handler #74");
    335 
    336    /* onmousedown */
    337    test(function () { assert_true( events.indexOf('orange.onmousedown') != -1 ); }, "orange.onmousedown should fire");
    338    test(function () { assert_equals( events.filter(function (e) { if (e == 'orange.onmousedown') return e; }).length, 1); }, "orange.onmousedown should fire 1 time");
    339    test(function () { assert_equals( events[0], 'orange.onmousedown' ); }, "orange.onmousedown should be event handler #1");
    340    test(function () { assert_equals( events.indexOf('pink.onmousedown'), -1 ); }, "pink.onmousedown should not fire");
    341    test(function () { assert_equals( events.indexOf('yellow.onmousedown'), -1 ); }, "yellow.onmousedown should not fire");
    342    test(function () { assert_equals( events.indexOf('blue.onmousedown'), -1 ); }, "blue.onmousedown should not fire");
    343    test(function () { assert_equals( events.indexOf('body.onmousedown'), -1 ); }, "onmousedown should not fire at body");
    344    test(function () { assert_true( events.indexOf('bubble.onmousedown') != -1 ); }, "onmousedown should bubble to body");
    345    test(function () { assert_equals( events.filter(function (e) { if (e == 'bubble.onmousedown') return e; }).length, 1); }, "onmousedown should bubble to body 1 time");
    346    test(function () { assert_equals( events[1], 'bubble.onmousedown' ); }, "onmousedown should bubble to body as event handler #1");
    347 
    348    /* onmouseup */
    349    test(function () { assert_equals( events.indexOf('orange.onmouseup'), -1 ); }, "orange.onmouseup should not fire");
    350    test(function () { assert_equals( events.indexOf('pink.onmouseup'), -1 ); }, "pink.onmouseup should not fire");
    351    test(function () { assert_equals( events.indexOf('yellow.onmouseup'), -1 ); }, "yellow.onmouseup should not fire");
    352    test(function () { assert_equals( events.indexOf('blue.onmouseup'), -1 ); }, "blue.onmouseup should not fire");
    353    test(function () { assert_equals( events.indexOf('body.onmouseup'), -1 ); }, "onmouseup should not fire at body");
    354    test(function () { assert_equals( events.indexOf('bubble.onmouseup'), -1 ); }, "onmouseup should not bubble to body");
    355 
    356    done();
    357  }
    358 };
    359 </script>
    360 
    361 <div id="testhere">
    362 <div draggable='true' id='orange'></div>
    363 <div id='fuchsia'></div>
    364 <div id='yellow'></div>
    365 <div id='blue'></div>
    366 </div>
    367 
    368 <p>If you have already clicked on this page, reload it.</p>
    369 <p>Use your pointing device to slowly drag the orange square over the pink square then the yellow square, then the blue square, and release it over the blue square (make sure the mouse remains over each square for at least 1 second, and over the gaps between squares for at least 1 second). Fail if no new text appears below.</p>
    370 
    371 <div id="log"></div>