2017-05-04 6 views
8

Trudno jest podsumować ten błąd słowami. Zrobiłem więc video dla błędu. Zasadniczo po wywołaniu funkcji dragEnd element animuje się tak, jakby przechodził do oryginalnego miejsca. Jak zatrzymać domyślne zachowanie? Zrobiłem też fiddle i codepen.Jak zatrzymać domyślne zachowanie dragend w przeciągnięciu i upuszczeniu?

Mam dwie listy dla mojego przykładu, podczas wywoływania dragEnd po zwolnieniu przycisku myszy. Element z jednej listy animuje listę oryginalnych miejsc zamiast miejsca, w którym ma się znaleźć. Kod

JS:

'use strict'; 

var source = null; var heightWidth = null; var lastDragOverElementId = null; var dragImageSource = null; 

function listItemDragStartHandler(event) { 
    source = event.currentTarget; 
    heightWidth = []; 
    heightWidth.push(source.offsetHeight); 
    heightWidth.push(source.offsetWidth); 
    event.dataTransfer.setData('text/html', event.currentTarget.innerHTML); 
    event.dataTransfer.effectAllowed = 'move'; 
    // Drag image logic 
    dragImageSource = source.cloneNode(true); 
    dragImageSource.style.position = 'absolute'; 
    // Don't show the element 
    dragImageSource.style.top = '0px'; 
    dragImageSource.style.left = '-' + String(window.innerWidth) + 'px'; 
    // dragImageSource.style.left = '-100px'; 
    var toTiltElement = dragImageSource.getElementsByClassName('item-list-element')[0]; 
    toTiltElement.style.transform = 'rotate(5deg)'; 
    document.body.append(dragImageSource); 
    event.dataTransfer.setDragImage(dragImageSource, heightWidth[1]/2, heightWidth[0]/2); } 

function dragoverHandler(event) { 
    event.preventDefault(); 
    event.dataTransfer.dropEffect = 'move'; 
    source.style.display = 'none'; 
    var currentElement = event.currentTarget; 
    var listContainer = currentElement.parentNode; 
    if (lastDragOverElementId != currentElement.getAttribute('id')) { 
     lastDragOverElementId = currentElement.getAttribute('id'); 
     if(document.getElementById('grayed-empty-node') !== null) { 
      if(currentElement.getAttribute('id') !== 'grayed-empty-node') { 
       document.getElementById('grayed-empty-node').remove(); 
      } 
     } 
     var isGrayEmptyNodeThere = document.getElementById('grayed-empty-node'); // 
     if(isGrayEmptyNodeThere === null) { 
      var emptyNode = document.getElementById('empty-node').cloneNode(true); 
      emptyNode.removeAttribute('id'); 
      emptyNode.setAttribute('id', 'grayed-empty-node'); 
      emptyNode.setAttribute('class', 'fade-in'); 
      emptyNode.style.height = String(heightWidth[0]) + 'px'; 
      emptyNode.style.width = String(heightWidth[1]) + 'px'; 
      listContainer.insertBefore(emptyNode, currentElement); 
     } 
    } } 

function dragLeaveHandler(event) { 
    event.preventDefault(); 
    var currentElement = event.currentTarget; 
    var listContainer = currentElement.parentNode; 
    var elementList = listContainer.getElementsByClassName('item-template-container'); 
    var visibleElementList = []; 
    var i = 0; 
    for (i=0; i<elementList.length; i++) { 
     if (elementList[i].style.display !== 'none') { 
      visibleElementList.push(elementList[i]); 
     } 
    } 
    // Last element ondragleave handler should be delayed, otherwise it 
    // would spin off chain reaction. 
    var lastVisibleElement = visibleElementList[visibleElementList.length - 1]; 
    // Basically last element 
    if (currentElement.id === lastVisibleElement.getAttribute('id')) { 
     lastVisibleElement.removeAttribute('ondragleave'); 
     if(document.getElementById('grayed-empty-node') !== null) { 
      document.getElementById('grayed-empty-node').remove(); 
     } 
     var isGrayEmptyNodeThere = document.getElementById('grayed-empty-node'); 
     if(isGrayEmptyNodeThere === null) { 
      var listContainer = currentElement.parentNode; 
      var emptyNode = document.getElementById('empty-node').cloneNode(true); 
      emptyNode.removeAttribute('id'); 
      emptyNode.setAttribute('id', 'grayed-empty-node'); 
      emptyNode.setAttribute('class', 'fade-in'); 
      emptyNode.style.height = String(heightWidth[0]) + 'px'; 
      emptyNode.style.width = String(heightWidth[1]) + 'px'; 
      listContainer.insertBefore(emptyNode, null); 
     } 
     // This delayed the chain reaction 
     setTimeout(function() { 
      visibleElementList[visibleElementList.length - 1].setAttribute('ondragleave', 'dragLeaveHandler(event);'); 
     }, 500); 
    // When event is on last element set the lastDragOverElementId to null 
    // then dragover to lastVisibleElement(second last element) can be handled 
    // otherwise dragover to second last element won't show placeholder. 
    lastDragOverElementId = null; 
    } } 

function dragEndHandler(event) { 
    event.preventDefault(); 
    // Check the dropEffect 
    dragImageSource.remove(); 
    var listElement = document.getElementById('grayed-empty-node') 
    var listContainer = listElement.parentNode; 
    if (event.dataTransfer.dropEffect === 'none') { 
     var grayEmptyNode = document.getElementById('grayed-empty-node'); 
     // When grayEmptyNode is null, that will append at the end. 
     listContainer.insertBefore(source, grayEmptyNode); 
     source.style.display = ''; 
     if(document.getElementById('grayed-empty-node') !== null) { 
      document.getElementById('grayed-empty-node').remove(); 
     } 
    } else if (event.dataTransfer.dropEffect === 'move') { 
     var grayEmptyNode = document.getElementById('grayed-empty-node'); 
     // When grayEmptyNode is null, that will append at the end. 
     listContainer.insertBefore(source, grayEmptyNode); 
     source.style.display = ''; 
     if(document.getElementById('grayed-empty-node') !== null) { 
      document.getElementById('grayed-empty-node').remove(); 
     } 
    } } 

function delete_item(event) { 
    var currentElement = event.currentTarget; 
    var grandParentOfDelete = currentElement.parentNode.parentNode; 
    grandParentOfDelete.remove(); } 

function add_item() { 
    var item_text_node = document.getElementsByName('add-item-text')[0] 
    var item_text = item_text_node.value; 
    if (item_text.length > 0) { 
     var item_template = document.getElementById('item-template-container'); 
     var item_clone = item_template.cloneNode(true); 
     item_clone.removeAttribute('id'); 
     var random_id = (new Date().getTime() + 
      parseInt(Math.random(0, 1000) * 1000)) 
     item_clone.setAttribute('id', random_id); 
     var clone_text = item_clone.getElementsByClassName('item-text')[0]; 
     clone_text.textContent = item_text; 
     // reset the value 
     item_text_node.value = ''; 
     var item_list = document.getElementById('item-list'); 
     item_list.appendChild(item_clone); 
    } else { 
     alert('No text?? Add some text!'); 
    } } 

function add_item_2() { 
    var item_text_node = document.getElementsByName('add-item-text-2')[0] 
    var item_text = item_text_node.value; 
    if (item_text.length > 0) { 
     var item_template = document.getElementById('item-template-container'); 
     var item_clone = item_template.cloneNode(true); 
     item_clone.removeAttribute('id'); 
     var random_id = (new Date().getTime() + 
      parseInt(Math.random(0, 1000) * 1000)) 
     item_clone.setAttribute('id', random_id); 
     var clone_text = item_clone.getElementsByClassName('item-text')[0]; 
     clone_text.textContent = item_text; 
     // reset the value 
     item_text_node.value = ''; 
     var item_list = document.getElementById('item-list-2'); 
     item_list.appendChild(item_clone); 
    } else { 
     alert('No text?? Add some text!'); 
    } } 

function onEnterInInput() { 
    var e = e || window.event; 
    if (e.keyCode == 13) { 
     add_item() 
    } } 

function sample_data() { 
    for(var i=0;i<10;i++){ 
     var item_text_node = document.getElementsByName('add-item-text')[0] 
     item_text_node.value = i; 
     var item_text_node_2 = document.getElementsByName('add-item-text-2')[0] 
     item_text_node_2.value = i; 
     add_item(); 
     add_item_2(); 
    } } 

window.onload = function() { 
    sample_data(); } 

HTML kod:

<!DOCTYPE html> 
<html> 
<head> 
    <title>List task</title> 
    <script type="text/javascript" src="list-task.js"></script> 
    <link rel="stylesheet" type="text/css" href="list-task.css"> 
    <script> 
     document.write('<script src="http://' + (location.host || 'localhost').split(':')[0] + 
     ':35729/livereload.js?snipver=1"></' + 'script>') 
    </script> 
</head> 
<body> 
    <div id="container"> 
     <div id="list-1"> 
      <div id="add-item-div"> 
       <input type="text" name="add-item-text" onkeypress="onEnterInInput(event);"> 
       <button id="add-item" onclick="add_item(event)">Add Item</button> 
      </div> 
      <div id="item-list"> 
      </div> 
     </div> 
     <div id="list-2"> 
      <div id="add-item-div-2"> 
       <input type="text" name="add-item-text-2" onkeypress="onEnterInInput(event);"> 
       <button id="add-item-2" onclick="add_item_2(event)">Add Item</button> 
      </div> 
      <div id="item-list-2"> 
      </div> 
     </div> 
     <div id="item-template-container" class="item-template-container" draggable="true" ondragstart="listItemDragStartHandler(event);" ondragover="dragoverHandler(event);" ondragend="dragEndHandler(event);" ondragleave="dragLeaveHandler(event);" ondrop="onDropHandler(event);"> 
      <div class="item-list-element"> 
       <div class="item-text"></div> 
       <div class="delete-item-div"> 
        <button class="delete-item" onclick="delete_item(event);">Delete</button> 
       </div> 
      </div> 
     </div> 
     <div id="empty-node">&nbsp;</div> 
    </div> 
</body> 
</html> 

Film opisujący błąd: https://www.youtube.com/watch?v=Uz_ukKdg1O0&feature=youtu.be

Uwaga: I obserwowano zachowanie na Mac, nie wiesz o Linuksie i Windows.

+0

animacja nie działa w jsfiddle. –

+0

Działa bezpośrednio w komputerze z chromem. –

+0

OK, ale jak można w wideo, dzieje się to na wszystkich przeglądarkach Mac. Czy powinienem zrobić kolejne wideo? – igaurav

Odpowiedz

0

W module obsługi zdarzeń "przeciągnij" musisz wykryć, czy mysz znajduje się na szarym polu na liście, którą chcesz upuścić. Pamiętaj, że musisz napisać logikę, aby wysłać zapytanie do elementu grayBoxInOtherList, ale to właśnie będziesz trzeba zrobić:

if ($(grayBoxInOtherList).parent().find(":hover")) { 
    listContainer.insertBefore(source, grayEmptyNode); 
} 

Tylko to zrobić, jeśli jesteś zatrzymując nad grayBoxInOtherList: listContainer.insertBefore(source, grayEmptyNode);

+0

UX nie potrzebuje użytkownika do najechania kursorem na szare pole, użytkownik może zostawić go z dowolnego miejsca w przeglądarce. Więc to rozwiązanie nie jest tym, czego potrzebuję. – igaurav

+0

Z Twojego filmu myślałem, że chcesz powrócić do pierwotnej lokalizacji, jeśli nie wisiałeś nad szarym prostokątem na nowej liście podczas przeciągania. Czy możesz wyjaśnić pożądane zachowanie? –

Powiązane problemy