最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Restrict drop areas to some draggable elements - Stack Overflow

programmeradmin0浏览0评论

I have been working on a project thet needs HTML5 drag & drop and I'm stuck atm with something that probably would be so easy to achieve but I can't seem to find the solution.

Basically I have some draggable elements and some drop areas. As it's alwasy easier to explain with a working example I have made this simple JSFIDDLE

Right now You can drag any element into any drop area or move them out as I need, but what I would like to achieve is to make the orange boxes to drop JUST in any of the green areas (and ignore the blue one... make it move back to original position if you drop it there) and the red box JUST into the blue one (ignoring the green ones).

Could anyone help me or hint me a way to work on this?

    function DragOver(ev) {
      ev.preventDefault();
    }

    function Drag(ev) {
      ev.dataTransfer.setData("text", ev.target.id);
    }

    function Drop(ev) {
      ev.preventDefault();
      var data = ev.dataTransfer.getData("text");
      ev.target.appendChild(document.getElementById(data));
    }


    var elemens = document.querySelectorAll('.draggable');
    [].forEach.call(elemens, function(elem) {
      elem.addEventListener('dragover', DragOver, false);
      elem.addEventListener('drop', Drop, false);
    });
   #divContenedor {
     width: 950px;
     height: 500px;
   }
   
   #div1,
   #div2,
   #div3 {
     width: 350px;
     height: 70px;
     border: 1px solid #aaaaaa;
     background-color: green;
   }
   
   #div4 {
     width: 350px;
     height: 70px;
     border: 1px solid #aaaaaa;
     background-color: blue;
   }
<p>
  Drag&drop testing</p>
<div id="divContenedor" class="draggable" style="background-color: yellow; width: 100%; float: left; position: relative;">
  <div id="drag1" draggable="true" ondragstart="Drag(event)" style="width: 336px; height: 69px; background-color: orange; cursor: move;">1</div>
  <div id="drag2" draggable="true" ondragstart="Drag(event)" style="width: 336px; height: 69px; background-color: orange; cursor: move;">2</div>
  <div id="drag3" draggable="true" ondragstart="Drag(event)" style="width: 336px; height: 69px; background-color: red; cursor: move;">3</div>
</div>
<div style="position: absolute; top: 100px; left: 500px;">
  <div id="div1" class="draggable" ></div>
  <br />
  <div id="div2" class="draggable" ></div>
  <br />
  <div id="div3" class="draggable" ></div>
  <br />
  <div id="div4" class="draggable" ></div>
</div>

I have been working on a project thet needs HTML5 drag & drop and I'm stuck atm with something that probably would be so easy to achieve but I can't seem to find the solution.

Basically I have some draggable elements and some drop areas. As it's alwasy easier to explain with a working example I have made this simple JSFIDDLE

Right now You can drag any element into any drop area or move them out as I need, but what I would like to achieve is to make the orange boxes to drop JUST in any of the green areas (and ignore the blue one... make it move back to original position if you drop it there) and the red box JUST into the blue one (ignoring the green ones).

Could anyone help me or hint me a way to work on this?

    function DragOver(ev) {
      ev.preventDefault();
    }

    function Drag(ev) {
      ev.dataTransfer.setData("text", ev.target.id);
    }

    function Drop(ev) {
      ev.preventDefault();
      var data = ev.dataTransfer.getData("text");
      ev.target.appendChild(document.getElementById(data));
    }


    var elemens = document.querySelectorAll('.draggable');
    [].forEach.call(elemens, function(elem) {
      elem.addEventListener('dragover', DragOver, false);
      elem.addEventListener('drop', Drop, false);
    });
   #divContenedor {
     width: 950px;
     height: 500px;
   }
   
   #div1,
   #div2,
   #div3 {
     width: 350px;
     height: 70px;
     border: 1px solid #aaaaaa;
     background-color: green;
   }
   
   #div4 {
     width: 350px;
     height: 70px;
     border: 1px solid #aaaaaa;
     background-color: blue;
   }
<p>
  Drag&drop testing</p>
<div id="divContenedor" class="draggable" style="background-color: yellow; width: 100%; float: left; position: relative;">
  <div id="drag1" draggable="true" ondragstart="Drag(event)" style="width: 336px; height: 69px; background-color: orange; cursor: move;">1</div>
  <div id="drag2" draggable="true" ondragstart="Drag(event)" style="width: 336px; height: 69px; background-color: orange; cursor: move;">2</div>
  <div id="drag3" draggable="true" ondragstart="Drag(event)" style="width: 336px; height: 69px; background-color: red; cursor: move;">3</div>
</div>
<div style="position: absolute; top: 100px; left: 500px;">
  <div id="div1" class="draggable" ></div>
  <br />
  <div id="div2" class="draggable" ></div>
  <br />
  <div id="div3" class="draggable" ></div>
  <br />
  <div id="div4" class="draggable" ></div>
</div>

UPDATE JSFIDDLE with @Amen solution.

Share Improve this question edited Dec 21, 2015 at 12:17 Alvaro Menéndez asked Dec 21, 2015 at 11:23 Alvaro MenéndezAlvaro Menéndez 9,0323 gold badges40 silver badges58 bronze badges
Add a ment  | 

2 Answers 2

Reset to default 7

You can use data attributes logic and do following 3 simple modifications to achieve that

1) add to draggable elements attribute data-appendto="green" or blue

2) add to div elements where you dragable element should append data-boxtype="red" or blue

3) in Drop(ev) function you can check if your document.getElementById(data) and ev.target data attributes values are matching then allow drop. You can get elements data-attribute with js .getAttribute('data-attribute') function

if(ev.target.getAttribute('data-boxtype') == 
   document.getElementById(data).getAttribute('data-appendto')){

  ev.target.appendChild(document.getElementById(data));
}

Good answer Armen, but if you want to handle access on the dragover event, then add another attribute that says simply yes.

As you can see, I have 4 methods in my JavaScript module object that are all called from the drag and drop elements events.

Step 1. The OnDragStart event sets the stage by changing the data-ts-allowdrop attribute to "Yes" (its default is no), for all potential targets that match its drop element query. Assuming an element will accept more than 1 source, I perform a contains query to find the element and not an exact match

step 2. When dragged over the receiving element its DragOver Event will check its "data-ts-allowdrop" attribute to see if its been set to true or "Yes". If so, then it runs preventsDefault and the drop is allowed and handled by the OnDrop method which proceeds to turn off the "data-ts-allowdrop" attribute.

step 3. Also use the onEnd to set the "data-ts-allowdrop" to No in case the drag event is cancelled.

<div id="divName" draggable="true" ondragstart="tsjDragnDrop.setSource(event);" data-ts-drag-allow-source="admin" tabindex="1" ><span >Item to Drag</span><img alt="an icon" src="~/images/anImage.png"  /></div>

<li ondragover="tsjDragnDrop.allowTarget(event);" ondragleave="tsjDragnDrop.onLeave(event)" ondrop="tsjDragnDrop.onDrop(event)" data-ts-drag-allow-target="admin" data-ts-allowdrop="No" >Drop Target in a list item</li>


var DraggnApi = {
    allowTarget: function (event) {
            var source = $(event.currentTarget).attr("data-ts-allowdrop");
            $(event.currentTarget).addClass("ts-dragover");

            if (source === "Yes") {
                event.preventDefault();
            }
        },

        onLeave: function (event) {

            $(event.currentTarget).removeClass("ts-dragover");
        },

        onDrop: function (event) {
            event.preventDefault();
            var source = $(event.currentTarget).removeClass("ts-dragover");
            $(event.currentTarget).attr("data-ts-allowdrop", "No");
        },

        onEnd: function (event) {

            $(event.currentTarget).attr("data-ts-allowdrop", "No");
        },

        setSource: function(e)
        {
            e.dataTransfer.setData("text", "SomeText");

            var source = $(event.currentTarget).attr("data-ts-drag-allow-source");

            if ($("li[data-ts-drag-allow-target]").attr("data-ts-drag-allow-target").indexOf(source) > -1) {
                $("li[data-ts-drag-allow-target*='" + source + "']").attr("data-ts-allowdrop", "Yes");
            }
        }
    }
发布评论

评论列表(0)

  1. 暂无评论
ok 不同模板 switch ($forum['model']) { /*case '0': include _include(APP_PATH . 'view/htm/read.htm'); break;*/ default: include _include(theme_load('read', $fid)); break; } } break; case '10': // 主题外链 / thread external link http_location(htmlspecialchars_decode(trim($thread['description']))); break; case '11': // 单页 / single page $attachlist = array(); $imagelist = array(); $thread['filelist'] = array(); $threadlist = NULL; $thread['files'] > 0 and list($attachlist, $imagelist, $thread['filelist']) = well_attach_find_by_tid($tid); $data = data_read_cache($tid); empty($data) and message(-1, lang('data_malformation')); $tidlist = $forum['threads'] ? page_find_by_fid($fid, $page, $pagesize) : NULL; if ($tidlist) { $tidarr = arrlist_values($tidlist, 'tid'); $threadlist = well_thread_find($tidarr, $pagesize); // 按之前tidlist排序 $threadlist = array2_sort_key($threadlist, $tidlist, 'tid'); } $allowpost = forum_access_user($fid, $gid, 'allowpost'); $allowupdate = forum_access_mod($fid, $gid, 'allowupdate'); $allowdelete = forum_access_mod($fid, $gid, 'allowdelete'); $access = array('allowpost' => $allowpost, 'allowupdate' => $allowupdate, 'allowdelete' => $allowdelete); $header['title'] = $thread['subject']; $header['mobile_link'] = $thread['url']; $header['keywords'] = $thread['keyword'] ? $thread['keyword'] : $thread['subject']; $header['description'] = $thread['description'] ? $thread['description'] : $thread['brief']; $_SESSION['fid'] = $fid; if ($ajax) { empty($conf['api_on']) and message(0, lang('closed')); $apilist['header'] = $header; $apilist['extra'] = $extra; $apilist['access'] = $access; $apilist['thread'] = well_thread_safe_info($thread); $apilist['thread_data'] = $data; $apilist['forum'] = $forum; $apilist['imagelist'] = $imagelist; $apilist['filelist'] = $thread['filelist']; $apilist['threadlist'] = $threadlist; message(0, $apilist); } else { include _include(theme_load('single_page', $fid)); } break; default: message(-1, lang('data_malformation')); break; } ?>