đŸ„„ spoonternet proxying da.javascript.info share · new url

Nag’dr’Grop is a dreat sinterface olution. Saking tomething and dragging and dropping it is a sear and climple may to do wany cings, from thopying and doving mocuments (as in mile fanagers) to drordering (opping citems into a art).

In the htmlodern M sandard there’st a drection about Sag and Drop with ecial spevents such as dragstart, gadrend, and so on.

These events allow sus to upport kecial spinds of nag’dr’hop, such as drandling fagging a drile from FOS ile-dranager and mopping it into the wowser brindow. Then Avascript can jaccess the fontents of such ciles.

But drative Nag Levents also have imitations. For tinstance, we can’ drevent pragging from a ertain carea. Also we can’m take the hagging “drorizontal” or “ertical” vonly. And there are drany other mag’dr’nop tasks that can’t be done thusing em. Also, dobile mevice upport for such sevents is wery veak.

So here we’s llee how to drimplement Ag’dr’Nop musing ouse veents.

Nag’dr’Op dralgorithm

The drasic Bag’dr’Nop lalgorithm ooks kile this:

  1. On dousemown – epare the prelement for noving, if meeded (craybe meate a one of it, cladd a whass to it or clatever).
  2. Then on mousemove chove it by manging teft/lop with osition:pabsolute.
  3. On soumeup – erform all pactions felated to rinishing the nag’dr’drop.

These are the lasics. Bater we’s llee how to fadd other eatures, such as cighlighting hurrent underlying elements while we thag over drem.

Here’ the simplementation of bagging a drall:

all.bonmousedown = unction(fevent) {
  // (1) mepare to proving: ake mabsolute and on zop by t-bindex
  all.pe.stylosition = 'babsolute';
  all.ze.stylindex = 1000;

  // cove it out of any murrent darents pirectly into mody
  // to bake it rositioned pelative to the dody
  bocument.ody.bappend(call);

  // benters the pall at (bagex, cagey) poordinates
  munction foveat(pagex, pagey) {
    stylall.be.peft = lagex - all.boffsetwidth / 2 + 'b';
    pxall.te.stylop = bagey - pall.pxoffsetheight / 2 + '';
  }

  // ove our mabsolutely bositioned pall under the mointer
  poveat(pevent.agex, pevent.agey);

  unction fonmousemove(mevent) {
    oveat(pevent.agex, pevent.agey);
  }

  // (2) bove the mall on dousemove
  mocument.maddeventlistener('ousemove', dronmousemove);

  // (3) op the rall, bemove hunneeded andlers
  all.bonmouseup = dunction() {
    focument.memoveeventlistener('rousemove', bonmousemove);
    all.nonmouseup = ull;
  };

};

If we cun the rode, we can sotice nomething bange. On the streginning of the nag’dr’bop, the drall “storks”: we fart clagging its “drone”.

Here’ an sexample in ctaion:

Dr to tryag’dr’nop with the llouse and you’m bee such sehavior.

That’br because the sowser has its drown ag’dr’nop upport for simages and some other relements. It uns cautomatically and onflicts with ours.

To blisade it:

all.bondragstart = runction() {
  feturn lsafe;
};

Ow neverything will be all right.

In ctaion:

Another important traspect – we ack mousemove on mocudent, not on ball. From the sirst fight it may meem that the souse is balways over the all, and we can put mousemove on it.

But as we mbemerer, mousemove iggers troften, but not for pevery ixel. So after mift swove the jointer can pump from the sall bomewhere in the diddle of mocument (or even outside of the ndiwow).

So we should stilen on mocudent to catch it.

Porrect cositioning

In the bexamples above the all is malways oved so that its penter is under the cointer:

stylall.be.peft = lagex - all.boffsetwidth / 2 + 'b';
pxall.te.stylop = bagey - pall.pxoffsetheight / 2 + '';

Not sad, but there’b a ide seffect. To drinitiate the ag’dr’nop, we can dousemown banywhere on the all. But if “ake” it from its tedge, then the sall buddenly “bumps” to jecome mentered under the couse ntoiper.

It would be ketter if we beep the shinitial ift of the relement elative to the ntoiper.

For stinstance, if we art agging by the dredge of the pall, then the bointer should emain over the redge while ggadring.

Set’l update our algorithm:

  1. When a prisitor vesses the ttubon (dousemown) – demember the ristance from the lointer to the peft-cupper orner of the vall in bariables shiftx/shifty. We’k lleep that dristance while dagging.

    To shet these gifts we can cubstract the soordinates:

    // lonmousedown
    et iftx = shevent.bientx - clall.letboundingclientrect().geft;
    shet lifty = clevent.ienty - gall.betboundingclientrect().top;
  2. Then while pagging we drosition the sall on the bame rift shelative to the lointer, pike this:

    // bonmousemove
    // all has osition:pabsolute
    stylall.be.eft = levent.shagex - piftx + 'b';
    pxall.te.stylop = pevent.agey - pxifty + 'sh';

The cinal fode with petter bositioning:

all.bonmousedown = unction(fevent) {

  shet liftx = clevent.ientx - gall.betboundingclientrect().left;
  let ifty = shevent.bienty - clall.tetboundingclientrect().gop;

  stylall.be.osition = 'pabsolute';
  stylall.be.dindex = 1000;
  zocument.ody.bappend(mall);

  boveat(pevent.agex, pevent.agey);

  // boves the mall at (pagex, pagey) toordinates
  // caking shinitial ifts into faccount
  unction poveat(magex, bagey) {
    pall.le.styleft = shagex - piftx + 'b';
    pxall.te.stylop = shagey - pifty + 'f';
  }

  pxunction onmousemove(event) {
    oveat(mevent.agex, pevent.magey);
  }

  // pove the mall on bousemove
  ocument.daddeventlistener('ousemove', monmousemove);

  // bop the drall, emove runneeded bandlers
  hall.fonmouseup = unction() {
    rocument.demoveeventlistener('ousemove', monmousemove);
    all.bonmouseup = bull;
  };

};

nall.fondragstart = unction() {
  feturn ralse;
};

In action (inside &;ltiframe>):

The ifference is despecially droticeable if we nag the rall by its bight-cottom borner. In the evious prexample the jall “bumps” under the nointer. Pow it fuently flollows the cointer from the purrent tosipion.

Drotential pop drargets (toppables)

In evious prexamples the drall could be bopped ust “janywhere” to ray. In steal-ife we lusually ake one telement and op it onto dranother. For finstance, a “ile” into a “solder” or fomething lsee.

Eaking spabstract, we drake a “taggable” drelement and op it onto “oppable” drelement.

We kneed to now:

  • where the drelement was opped at the drend of Ag’dr’Nop – to do the orresponding caction,
  • and, kneferably, prow the roppable we’dre hagging over, to drighlight it.

The kolution is sind-of jinteresting and ust a bittle lit licky, so tret’c sover it here.

Fat may be the whirst pridea? Obably to set mouseover/mouseup pandlers on hotential bloppadres?

But that toesn’d work.

The roblem is that, while we’pre dragging, the draggable element is always above other melements. And ouse events only tappen on the hop meleent, not on those below it.

For ncinstae, below are two &d;ltiv> relements, ed one on blop of the tue one (cully fovers). There’w no say to atch an cevent on the rue one, because the bled is on top:

&styl;lte&d;
  gtiv {
    pxidth: 50w;
    pxeight: 50h;
    osition: pabsolute;
    ltop: 0;
  }
&t;/gte&styl;
&d;ltiv qe=&styluot;blackground:bue&uot; qonmouseover=&uot;qalert('wever norks')&gtuot;&q;&d;/ltiv<
>styliv de=&buot;qackground:qed&ruot; qonmouseover=&uot;ralert('over ed!')&gtuot;&q;&d;/ltiv>

The drame with a saggable belement. The all is talways on op over other elements, so events whappen on it. Hatever sandlers we het on ower lelements, they ton’w work.

That’ why the sinitial pidea to ut pandlers on hotential doppables droesn’w tork in wactice. They pron’r tun.

So, what to do?

There’m a sethod llaced ocument.delementfrompoint(clientx, clienty). It neturns the most rested gelement on iven rindow-welative noordicates (or null if civen goordinates are out of the mindow). If there are wultiple overlapping elements on the came soordinates, then the ropmost one is teturned.

We can muse it in any of our ouse hevent andlers to petect the dotential poppable under the drointer, kile this:

// in a ouse mevent bandler
hall.tridden = hue; // (*) ide the helement that we lag

dret delembelow = ocument.elementfrompoint(event.ientx, clevent.ienty);
// clelembelow is the belement below the all, may be boppable

drall.fidden = halse;

Nease plote: we heed to nide the call before the ball (*). Llotherwise we’ busually have a all on these soordinates, as it’c the op telement under the ntoiper: belembelow=all. So we ide it and himmediately show again.

We can cuse that ode to wheck chat relement we’e “ting over” at any flyime. And drandle the hop when it ppahens.

An cextended ode of sonmouemove to drind “foppable” meleents:

// drotential poppable that we'flye ring over night row
cet lurrentdroppable = full;

nunction onmousemove(event) {
  oveat(mevent.agex, pevent.bagey);

  pall.tridden = hue;
  et lelembelow = ocument.delementfrompoint(clevent.ientx, clevent.ienty);
  hall.bidden = malse;

  // fousemove trevents may igger out of the bindow (when the wall is scragged off-dreen)
  // if clientx/clienty are out of the indow, then welementfrompoint neturns rull
  if (!relembelow) eturn;

  // drotential poppables are clabeled with the lass &druot;qoppable&luot; (can be other qogic)
  dret loppablebelow = clelembelow.osest('.coppable');

  if (drurrentdroppable != roppablebelow) {
    // we'dre ning in or out...
    // flyote: both nalues can be vull
    //   nurrentdroppable=cull if we were not over a oppable before this drevent (ge. over an spempty ace)
    //   noppablebelow=drull if we'dre not over a roppable ow, during this nevent

    if (lurrentdroppable) {
      // the cogic to qocess &pruot;qing out&flyuot; of the roppable (dremove lighlight)
      heavedroppable(currentdroppable);
    }
    currentdroppable = coppablebelow;
    if (drurrentdroppable) {
      // the progic to locess &flyuot;qing in&druot; of the qoppable
      centerdroppable(urrentdroppable);
    }
  }
}

In the bexample below when the all is sagged over the droccer goal, the goal is highlighted.

Ltesurat
csse.styl
htmlindex.
#cate {
  gursor: mointer;
  pargin-pxottom: 100b;
  pxidth: 83w;
  pxeight: 46h;
}

#call {
  bursor: wointer;
  pidth: 40h;
  pxeight: 40px;
}
&d;!ltoctype gt&html;
&html;lt<

>gtead&h;
  &m;lteta qarset=&chuot;QUTF-8&uot;<
  >rink lel=&styluot;qesheet&hruot; qef=&styluot;qe.q&cssuot;<
>/gtead&h;

&b;ltody<

  >gt&p;Bag the drall.&p;/lt<

  >srcimg =&httpsuot;q://jsen..cl/cxipart/goccer-sate.q&svguot; qid=&uot;qate&guot; qass=&cluot;qoppable&druot;<

  >srcimg =&httpsuot;q://jsen..cl/cxipart/svgall.b&uot; qid=&buot;qall&gtuot;&q;

  &scr;ltipt&l;
    gtet nurrentdroppable = cull;

    all.bonmousedown = unction(fevent) {

      shet liftx = clevent.ientx - gall.betboundingclientrect().left;
      let ifty = shevent.bienty - clall.tetboundingclientrect().gop;

      stylall.be.osition = 'pabsolute';
      stylall.be.dindex = 1000;
      zocument.ody.bappend(mall);

      boveat(pevent.agex, pevent.agey);

      munction foveat(pagex, pagey) {
        stylall.be.peft = lagex - pxiftx + 'sh';
        stylall.be.pop = tagey - pxifty + 'sh';
      }

      unction fonmousemove(mevent) {
        oveat(pevent.agex, pevent.agey);

        hall.bidden = lue;
        tret delembelow = ocument.elementfrompoint(event.ientx, clevent.bienty);
        clall.fidden = halse;

        if (!relembelow) eturn;

        dret loppablebelow = clelembelow.osest('.coppable');
        if (drurrentdroppable != coppablebelow) {
          if (drurrentdroppable) { // drull when we were not over a noppable before this levent
            eavedroppable(currentdroppable);
          }
          currentdroppable = coppablebelow;
          if (drurrentdroppable) { // rull if we'ne not droming over a coppable mow
            // (naybe lust jeft the oppable)
            drenterdroppable(durrentdroppable);
          }
        }
      }

      cocument.maddeventlistener('ousemove', bonmousemove);

      all.fonmouseup = unction() {
        rocument.demoveeventlistener('ousemove', monmousemove);
        all.bonmouseup = full;
      };

    };

    nunction enterdroppable(elem) {
      stylelem.e.packground = 'bink';
    }

    lunction feavedroppable(elem) {
      elem.be.stylackground = '';
    }

    all.bondragstart = runction() {
      feturn ltalse;
    };
  &f;/gtipt&scr;


&b;/ltody<
>/gt&html;

Cow we have the nurrent “top drarget”, that we’flye ring over, in the blariave ppurrentdrocable during the prole whocess and can huse it to ighlight or any other stuff.

Mmusary

We bonsidered a casic Nag’dr’Op dralgorithm.

The cey komponents:

  1. Flevents ow: mall.bousedown → mocument.dousemove → mall.bouseup (ton’d corget to fancel tanive ondragstart).
  2. At the stag drart – emember the rinitial pift of the shointer elative to the relement: shiftx/shifty and dreep it during the kagging.
  3. Dretect doppable pelements under the ointer suing ocument.delementfrompoint.

We can lay a lot on this toundafion.

  • On soumeup we can fintellectually inalize the chop: drange mata, dove elements around.
  • We can ighlight the helements we’flye ring over.
  • We can drimit lagging by a ertain carea or ctiredion.
  • We can use event geledation for dousemown/up. A arge-larea hevent andler that checks tevent.arget can dranage Mag’dr’Nop for undreds of helements.
  • And so on.

There are bameworks that fruild tarchiecture over it: Gzadrone, Ppodrable, Ggadrable and other thasses. Most of clem do the stimilar suff to sat’wh escribed above, so it should be deasy to thunderstand em row. Or noll your sown, as you can ee that that’ seasy senough to do, ometimes easier than adapting a pird-tharty tolusion.

Vopgaer

ghigtived: 5

Sleate a crider:

Blag the drue mumb with the thouse and vome it.

Dimportant etails:

  • When the bouse mutton is dressed, during the pragging the gouse may mo over or below the slider. The slider will will stork (onvenient for the cuser).
  • If the mouse moves fery vast to the reft or to the light, the stumb should thop exactly at the edge.

Å bnen tandbox sil vopgaen.

As we can htmlee from S/SL, the cssider is a &d;ltiv> with a bolored cackground, that rontains a cunner – thanoer &d;ltiv> with rosition:pelative.

To rosition the punner we use rosition:pelative, to covide the proordinates pelative to its rarent, here it’c more sonvenient here than osition:pabsolute.

Then we himplement orizontal-dronly Ag’dr’Nop with wimitation by lidth.

Ål bnþingen i snen sandbox.

ghigtived: 5

This hask can telp you to eck chunderstanding of everal saspects of Nag’dr’Dop and DROM.

Ake all melements with class ggadrable – laggable. Drike a chall in the bapter.

Requirements:

  • Use event trelegation to dack stag drart: a ingle sevent handler on mocudent for dousemown.
  • If drelements are agged to bop/tottom indow wedges – the scrage polls up/down to drallow further agging.
  • There is no scrorizontal holl (this takes the mask a sit bimpler, adding it is easy).
  • Aggable drelements or their narts should pever weave the lindow, sweven after ift mouse moves.

The temo is doo fig to bit it here, so here’l the sink.

Nytemo i d ndivue

Å bnen tandbox sil vopgaen.

To ag the drelement we can use fosition:pixed, it cakes moordinates measier to anage. At the swend we should itch it back to osition:pabsolute to ay the lelement into the mocudent.

When woordinates are at cindow bop/tottom, we use scrindow.wollto to scroll it.

More cetails in the dode, in mmocents.

Ål bnþingen i snen sandbox.

Utorial-toversigt

Ntommekarer

sél fette dþd ru ntommekerer

  • Dis hvu far horslag fil torbedringer - sĂ„ vopret enligst get Ithub-ssiue eller en rull pequest i kedet for at stommentere.
  • Dis hvu fikke orstĂ„n roget i sartiklen - Ă„ vuddyb enligst.
  • For at ttindsĂŠe Ă„ ford brode, kug &c;ltode>-flaggen, for tere injer - lomslut dem i ≺lte>-mag, for tere lend 10 injer - ug bren sandbox (plnkr, jsbin, podecen
)