বাচ্চাদের উপাদানগুলিকে টেনে আনলে পিতামাতার উপাদানগুলির 'ড্রাগলভেভ' আগুন ধরিয়ে দেয়


163

সংক্ষিপ্ত বিবরণ

আমার নিম্নলিখিত HTML গঠন আছে এবং আমি উপাদানগুলি dragenterএবং dragleaveইভেন্টগুলি সংযুক্ত করেছি attached<div id="dropzone">

<div id="dropzone">
    <div id="dropzone-content">
        <div id="drag-n-drop">
            <div class="text">this is some text</div>
            <div class="text">this is a container with text and images</div>
        </div>
    </div>
</div>

সমস্যা

আমি যখন কোনও ফাইল টেনে আনি <div id="dropzone">, তখন dragenterঘটনাটি প্রত্যাশার সাথে সরিয়ে ফেলা হয়। যাইহোক, যখন আমি কোনও শিশু মৌলের উপর দিয়ে আমার মাউসটি সরান, যেমন <div id="drag-n-drop">, dragenterইভেন্টটি <div id="drag-n-drop">উপাদানটির জন্য চালিত হয় এবং তারপরে dragleaveইভেন্টটির জন্য গুলি চালানো হয়<div id="dropzone"> উপাদানটির নিক্ষেপ করা হয়।

যদি আমি <div id="dropzone">আবার উপাদানটির উপরে ঘোরাফেরা করি তবে dragenterইভেন্টটি আবারো গুলি চালানো হবে, যা দুর্দান্ত, তবে তারপরে dragleaveইভেন্টটি শিশু উপাদানটির জন্য ঠিক রেখে দেওয়া হয়েছে, তাইremoveClass নির্দেশ মৃত্যুদন্ড কার্যকর করা হয়, যা ঠান্ডা করা হয় না।

এই আচরণটি 2 কারণে সমস্যাযুক্ত:

  1. আমি শুধু সংযুক্ত করছি dragenter& dragleaveকরতে <div id="dropzone">তাই আমি বুঝতে পারছি না কেন শিশুদের উপাদান এই ঘটনা পাশাপাশি সংযুক্ত আছে।

  2. আমি <div id="dropzone">বাচ্চাদের উপর ঘুরে বেড়াতে গিয়ে উপাদানটির উপরে এখনও টানছি যাতে আমি গুলি চালাতে চাই না dragleave!

jsFiddle

এখানে টিঙ্কার করার জন্য একটি জেএসফিডেল রয়েছে: http://jsfiddle.net/yYF3S/2/

প্রশ্ন

সুতরাং ... আমি কীভাবে এটি তৈরি করতে পারি যে আমি যখন কোনও <div id="dropzone">উপাদানটি যখন কোনও ফাইলকে টেনে আনি, তখন আমি dragleaveকোনও বাচ্চার উপাদানকে টেনে নিয়ে যাই তা চালানো হয় না ... যখন আমি <div id="dropzone">উপাদানটি রেখে যাই তখনই এটি চালিত হওয়া উচিত .. । উপাদানটির সীমানার মধ্যে যে কোনও জায়গায় ঘোরাফেরা / টেনে আনলে ঘটনাটি ট্রিগার করা উচিত নয়dragleave

কমপক্ষে HTML5 ড্রাগ-এন-ড্রপ সমর্থনকারী ব্রাউজারগুলিতে আমার এটি ক্রস ব্রাউজারের সাথে সামঞ্জস্যপূর্ণ হওয়া দরকার so সুতরাং এই উত্তরটি পর্যাপ্ত নয়।

দেখে মনে হচ্ছে গুগল এবং ড্রপবক্স এটিকে খুঁজে পেয়েছে তবে তাদের উত্স কোডটি ছোট / জটিল করা হয়েছে তাই আমি তাদের প্রয়োগ থেকে এটিকে বের করতে সক্ষম হইনি।


এর মাধ্যমে ইভেন্টের প্রচার বন্ধ করুনe.stopPropagation();
ব্লেন্ডার

আমি মনে করি আমি ইতিমধ্যে ... আপডেটটি দেখুন
Hristo

আপনি jsfiddle.net এ কোথাও একটি ডেমো পোস্ট করতে পারেন লোকেরা এটির সাথে টিঙ্কার করতে পারে?
ব্লেন্ডার

@ ব্লেন্ডার ... নিশ্চিত জিনিস, আমাকে কয়েক মিনিট দিন!
Hristo

@ ব্লেন্ডার ... আমি আমার প্রশ্নটি একটি ফ্রিডল দিয়ে আপডেট করেছি
হিস্টো

উত্তর:


171

আপনার যদি সন্তানের উপাদানগুলিতে ইভেন্টগুলি আবদ্ধ করার প্রয়োজন না হয় তবে আপনি সর্বদা পয়েন্টার-ইভেন্টের সম্পত্তিটি ব্যবহার করতে পারেন।

.child-elements {
  pointer-events: none;
}

4
সব থেকে ভালো সমাধান! আমি ভাবিনিও যে আমি এই জাতীয় মার্জিত উপায়ে সিএসএস ব্যবহার করে সমস্যার সমাধান করতে পারি। আপনাকে অনেক ধন্যবাদ!
serg66

1
ও আচ্ছা. এই হল!
mcmlxxxiii

23
এই পদ্ধতির একমাত্র নেতিবাচক দিকটি হ'ল এটি শিশু উপাদানগুলির সমস্ত পয়েন্টার ইভেন্টগুলিকে অনুগ্রহ করে (উদাহরণস্বরূপ তাদের আর পৃথক :hoverশৈলী বা ইভেন্ট হ্যান্ডলার ক্লিক করতে পারে না )। আপনি যদি এই ইভেন্টগুলি সংরক্ষণ করতে চান, এখানে আমি ব্যবহার করছি আরও একটি কার্যকারিতা
বেন

2
আপনার ড্রপজোনের সমস্ত শিশুদের কাছে পৌঁছানোর জন্য সিএসএস শিশু বাছাইকারী সাথে একত্রিত করুন: .dropzone * {pointer-events: none;}
ফিলিপ এফ

7
আপনি ইতিমধ্যে jQuery ব্যবহার করছেন, সুতরাং $('.element').addClass('dragging-over')আপনি যে উপাদানটি টেনে আনছেন ঠিক তেমন এবং $('.element').removeClass('dragging-over')আপনি যখন বাইরে টেনে আনেন। তারপরে আপনার সিএসএসে আপনি থাকতে পারেন .element.dragging-over * { pointer-events: none; }। এটি কেবলমাত্র যখন আপনি টেনে আনছেন তখন সমস্ত শিশু উপাদান থেকে পয়েন্টার ইভেন্টগুলি সরিয়ে দেয়।
গাভিন

56

অবশেষে আমি একটি সমাধান পেয়েছি যার সাথে আমি খুশি। আমি যা চাই তা করার জন্য আমি বেশ কয়েকটি উপায় খুঁজে পেয়েছি তবে বর্তমান সমাধানের মতো কোনওটিই সফল ছিল না ... একটি সমাধানে, আমি একটি সীমানা যুক্ত / সরানোর ফলে ঘন ঘন ঝাঁকুনির অভিজ্ঞতা পেয়েছি#dropzone উপাদানটিতে ... অন্যটিতে, সীমানা আপনি ব্রাউজার থেকে দূরে সরিয়ে থাকলে কখনও সরানো হয়নি।

যাইহোক, আমার সেরা হ্যাকির সমাধানটি হ'ল:

var dragging = 0;

attachEvent(window, 'dragenter', function(event) {

    dragging++;
    $(dropzone).addClass('drag-n-drop-hover');

    event.stopPropagation();
    event.preventDefault();
    return false;
});

attachEvent(window, 'dragover', function(event) {

    $(dropzone).addClass('drag-n-drop-hover');

    event.stopPropagation();
    event.preventDefault();
    return false;
});

attachEvent(window, 'dragleave', function(event) {

    dragging--;
    if (dragging === 0) {
        $(dropzone).removeClass('drag-n-drop-hover');
    }

    event.stopPropagation();
    event.preventDefault();
    return false;
});

এটি বেশ ভাল কাজ করে তবে ফায়ারফক্সে সমস্যাগুলি উপস্থিত হয়েছিল কারণ ফায়ারফক্স ডাবল-ইনভয়েটিং ছিল dragenter তাই আমার কাউন্টার বন্ধ ছিল। তবে তবুও এটি খুব মার্জিত সমাধান নয়।

তারপরে আমি এই প্রশ্নে হোঁচট খেয়েছি : উইন্ডোটির বাইরে টানা যখন ফায়ারফক্সে ড্রাগলভের ইভেন্টটি সনাক্ত করা যায়

সুতরাং আমি উত্তরটি নিয়েছি এবং এটি আমার পরিস্থিতিতে প্রয়োগ করেছি:

$.fn.dndhover = function(options) {

    return this.each(function() {

        var self = $(this);
        var collection = $();

        self.on('dragenter', function(event) {
            if (collection.size() === 0) {
                self.trigger('dndHoverStart');
            }
            collection = collection.add(event.target);
        });

        self.on('dragleave', function(event) {
            /*
             * Firefox 3.6 fires the dragleave event on the previous element
             * before firing dragenter on the next one so we introduce a delay
             */
            setTimeout(function() {
                collection = collection.not(event.target);
                if (collection.size() === 0) {
                    self.trigger('dndHoverEnd');
                }
            }, 1);
        });
    });
};

$('#dropzone').dndhover().on({
    'dndHoverStart': function(event) {

        $('#dropzone').addClass('drag-n-drop-hover');

        event.stopPropagation();
        event.preventDefault();
        return false;
    },
    'dndHoverEnd': function(event) {

        $('#dropzone').removeClass('drag-n-drop-hover');

        event.stopPropagation();
        event.preventDefault();
        return false;
    }
});

এটি পরিষ্কার এবং মার্জিত এবং মনে হয়েছে যে আমি এখন পর্যন্ত পরীক্ষিত প্রতিটি ব্রাউজারে কাজ করছি (এখনও IE পরীক্ষা করেন নি)।


এটি এখন অবধি সেরা সমাধান only কেবলমাত্র সমস্যাটি হ'ল এই কোডটি কাজ করে না যখন আপনি কোনও ফাইল যুক্ত করবেন, এটিকে সরিয়ে ফেলুন এবং এর উপর অন্য কোনও ফাইল টেনে আনুন। কেবল হোভারএন্ড উত্থাপন এবং আবার হোভারস্টার্ট উত্থাপনের পরে এই কোডটি আবার কাজ করে।
মিস্টিআরথ

@ মিস্টিকআরথ যখন কাজ না করে আপনি ডেমোতে একটি জেএসফিডেল একসাথে রাখতে পারেন?
হিস্টো

1
আপনার উত্তর করার জন্য আপনাকে ধন্যবাদ। এটি সত্যিই সহায়ক ছিল, কারণ এইচটিএমএল 5 ড্রাগ এবং ড্রপ ইন্টারফেস এবং ইভেন্ট শ্রোতারা সত্যিই বেদনাদায়ক হতে পারে। পাগল ইভেন্টগুলি হ্যান্ডেল করার এটি সর্বোত্তম উপায়, বিশেষত যখন আপনি ড্রপ জোন উপাদানগুলির একাধিক ঘটনা পরিচালনা করতে চান।
নিকো ও

কেন আমাদের স্টপপ্রপ্যাজেশন () প্রতিরোধ ডিফল্ট () কল করতে এবং মিথ্যা প্রত্যাবর্তন করতে হবে। মিথ্যা রিটার্ন যথেষ্ট হবে। ইহা উচিত ?
দেজো

এটি অনর্থক, তবে কল করা stopPropagation()এবং preventDefault()এটি পছন্দসই। আমি ড্রপ করব return false
Peeja

38

এটি কিছুটা কুৎসিত তবে এটি কাজ করে!

আপনার 'ড্রেজেটার' হ্যান্ডলারে ইভেন্ট.আরগেট (আপনার ক্লোজারের অভ্যন্তরে কোনও পরিবর্তনশীল বা যে কোনও কিছু) সংরক্ষণ করুন, তারপরে আপনার 'ড্রাগলভেভ' হ্যান্ডলারে কেবল ইভেন্ট কোডার === আপনার সঞ্চয় করা যদি আপনার কোডটি ফায়ার করে।

আপনি যখন এটি চান না তখন যদি আপনার 'ড্রেজেটার' গুলি চালাচ্ছে (যেমন শিশুদের উপাদান ছেড়ে যাওয়ার পরে এটি প্রবেশ করছে), তবে মাউস বাবা-মাকে ছেড়ে যাওয়ার আগে সর্বশেষে আগুন জ্বলছে, এটি পিতামাতার উপর রয়েছে, তাই পিতামাতা সর্বদা থাকবেন চূড়ান্ত 'dragenter' উদ্দেশ্য 'ড্রাগলেভ' এর আগে।

(function () {

    var droppable = $('#droppable'),
        lastenter;

    droppable.on("dragenter", function (event) {
        lastenter = event.target;
        droppable.addClass("drag-over");            
    });

    droppable.on("dragleave", function (event) {
        if (lastenter === event.target) {
            droppable.removeClass("drag-over");
        }
    });

}());

আমি পরে এই চেষ্টা করব। যদি কিছু হয় তবে এটি আমার সমাধানের চেয়ে আরও পরিষ্কার দেখায় তবে ক্রস ব্রাউজারটি কেবল এটি দেখে সামঞ্জস্যপূর্ণ তা আমি নিশ্চিত হতে পারি না। আপনি কোথায় এটি পরীক্ষা করেছেন?
Hristo

1
কেবলমাত্র ক্রোম, এবং কেবলমাত্র এই ধারণাটি নিয়ে কাজ করতে পারে যে শিশু উপাদান এবং ধারক মধ্যে শারীরিক ফাঁক রয়েছে।
হ্যাকলিক্যাক্র্যাক

5
আমার প্রিয় উত্তর এখানে। মোটেও কুৎসিত লাগে না :)
ম্যাট ওয়ে

1
আইই, ক্রোম, এফএফ
ভিসেন্টিয়ু ব্যাকিওইউ

1
বাচ্চাদের উপর টান শুরু করলে এটি কাজ করে না। উদাহরণস্বরূপ, অন্য উইন্ডো থেকে কোনও কিছু থেকে এমনভাবে টেনে নিয়ে যাওয়া যেভাবে শিশুর অভ্যন্তরে টানা শুরু হয়।
FINDarkside

29

প্রথমে, আমি লোকেরা এই pointer-events: noneপদ্ধতিটি বাতিল করে দিয়ে সম্মত হয়েছিল । তবে আমি নিজেকে জিজ্ঞাসা করেছি:

টেনে আনার প্রক্রিয়া চলাকালীন আপনার কি শিশু উপাদানগুলিতে কাজ করার জন্য পয়েন্টার-ইভেন্টগুলি সত্যই দরকার ?

আমার ক্ষেত্রে, আমার বাচ্চাদের মধ্যে প্রচুর পরিমাণে জিনিস চলছে, যেমন অতিরিক্ত ক্রিয়াকলাপ, ইনলাইন-সম্পাদনা ইত্যাদির জন্য বোতামগুলি দেখানোর জন্য হোভার করুন However তবে, এগুলির কোনওটি প্রয়োজনীয় নয় বা আসলে এমনকি কোনও টানানোর সময় পছন্দসই নয় ।

আমার ক্ষেত্রে, পিতামাতার ধারকের সমস্ত শিশু নোডের জন্য নির্বাচকভাবে পয়েন্টার ইভেন্টগুলি বন্ধ করতে আমি এই জাতীয় কিছু ব্যবহার করি:

  div.drag-target-parent-container.dragging-in-progress * {
    pointer-events: none;
  }

যোগ করার জন্য / বর্গ অপসারণ আপনার প্রিয় পদ্ধতির ব্যবহার করুন dragging-in-progressমধ্যে dragEnter/ dragLeave, ইভেন্ট হ্যান্ডলার হিসাবে আমি বা একই না dragStart, এট। অল।


1
এই সমাধান উভয়ই সহজ এবং সম্পূর্ণ প্রমাণ (যতদূর আমি বলতে পারি) পূর্ণ-প্রমাণ। কেবল dragstartইভেন্টটিতে ক্লাস যুক্ত করুন এবং এটিকে সরিয়ে দিন dragend
cmann

এটি বেশ চমৎকার সমাধান তবে নিখুঁত নয়। যদি সন্তানের উপাদানটিতে টানা শুরু হয় (অন্য উইন্ডো থেকে টানা), ড্রাগইন্টার কখনও বরখাস্ত হয় না। মাউসকে এত তাড়াতাড়ি স্থানান্তরিত করাও সম্ভব যে আপনি যখন সন্তানের কাছে যান তখন ড্রাগইন্টারটি বরখাস্ত হয় না, তবে এটি সম্পর্কে 100% নিশ্চিত নয়।
ফিন্ডার্কসাইড

12

এটি একটি ক্রোম বাগ বলে মনে হচ্ছে।

আমি কেবল ভাবতে পারি যে আপনার ইভেন্টগুলি ক্যাপচার করার জন্য একটি স্বচ্ছ ওভারলে উপাদান তৈরি করা হয়েছিল: http://jsfiddle.net/yYF3S/10/

জেএস :

$(document).ready(function() {
    var dropzone = $('#overlay');

    dropzone.on('dragenter', function(event) {
        $('#dropzone-highlight').addClass('dnd-hover');
    });

    dropzone.on('dragleave', function(event) {
        $('#dropzone-highlight').removeClass('dnd-hover');
    });

});​

এইচটিএমএল :

<div id="dropzone-highlight">
    <div id="overlay"></div>

    <div id="dropzone" class="zone">
        <div id="drag-n-drop">
            <div class="text1">this is some text</div>
            <div class="text2">this is a container with text and images</div>
        </div>
    </div>
</div>

<h2 draggable="true">Drag me</h2>

উত্তরের জন্য ধন্যবাদ, ব্লেন্ডার। আমি ইতিমধ্যে এটি চেষ্টা করেছি। এই সমাধানটির সাথে সমস্যাটি হ'ল ওভারলে উপাদানটি শিশুদের উপাদানগুলিকে "ওভারলে" করে, যার সাথে আমার ইন্টারঅ্যাক্ট করা দরকার ... সুতরাং ওভারলে থাকা আমার বাচ্চাদের সাথে যে ইন্টারঅ্যাকশন প্রয়োজন তা অক্ষম করে ... এটিকে একটি ফাইল ড্রাগ-এন হিসাবে ভাবেন -ড্রপ বক্স ... আপনি টানুন এবং ড্রপ করতে পারেন বা আপনার ফাইলগুলি নির্বাচন করতে ইনপুট উপাদানটি ক্লিক করতে পারেন।
হ্রিস্টো

আপনার সমাধানটি সন্তুষ্ট হয় না এমন একটি উদাহরণ এখানে আছে ... jsfiddle.net/UnsungHero97/yYF3S/11
Hristo

আমি বিভ্রান্ত আপনার পাশাপাশি শিশু উপাদানগুলির সাথেও আলাপচারিতা করা দরকার?
ব্লেন্ডার

আমার বিশেষ ক্ষেত্রে, "ড্রপজোন" এর একটি শিশু উপাদান ফাইল ফাইল বাটন ... তাই যদি আমি ফাইলগুলিকে টেনে আনতে না চাই, তবে আমি ইনপুট উপাদানটি ব্যবহার করে সেগুলি নির্বাচন করতে পারি। তবে ওভারলে দিয়ে ... আমি ইনপুট উপাদানটি ক্লিক করতে পারি না। ধারণা তৈরী কর?
হিস্টো

@ ব্লেন্ডার বেশিরভাগ ক্ষেত্রে আমাদের ডেস্কটপ থেকে একটি ফাইল টেনে আনতে হবে, পৃষ্ঠা থেকে কোনও উপাদান নয়, তাই এই ধরনের কাজ করে না।
মার্টিও ব্রিডিস

5

সমস্যাটি হ'ল, ড্রপজোনগুলির অভ্যন্তরে থাকা আপনার উপাদানগুলি অবশ্যই ড্রপজোনটির অংশ এবং আপনি যখন শিশুদের মধ্যে প্রবেশ করেন, আপনি পিতামাতাকে ছেড়ে যান। এটি সমাধান করা সহজ নয়। আপনি বাচ্চাদের সাথে ইভেন্টগুলি যুক্ত করার চেষ্টা করতে পারেন আবার আপনার ক্লাসটি পিতামাতার সাথে যুক্ত করে।

$("#dropzone,#dropzone *").on('dragenter', function(event) {

    // add a class to #dropzone

    event.stopPropagation(); // might not be necessary
    event.preventDefault();
    return false;
});

আপনার ইভেন্টগুলি এখনও একাধিকবার আগুন লাগবে তবে কেউ দেখতে পাবে না।

// সম্পাদনা: ড্র্যাগওয়েভ ইভেন্টটি স্থায়ীভাবে ওভাররাইট করতে ড্রাগগম ইভেন্টটি ব্যবহার করুন:

$("#dropzone,#dropzone *").on('dragenter dragover', function(event) {

    // add a class to #dropzone

    event.stopPropagation(); // might not be necessary
    event.preventDefault();
    return false;
});

ড্রপওয়েভ ইভেন্টটি কেবলমাত্র ড্রপজোনের জন্য সংজ্ঞা দিন।


2
এটি যদিও সমস্যার সমাধান করবে না। আসল বিষয়টি হ'ল dragleave... আমি যখন সন্তানকে ছেড়ে যাই, তখনও আমি পিতামাতার মধ্যে থাকতে পারি #dropzoneতবে dragenterঘটনাটি আবার প্রকাশ করবে না :(
হিস্টো

আপনি কি নিশ্চিত, যে ড্র্যাজেন্টারটি আবার বরখাস্ত করা হয়নি?
অলিভার

ঠিক আছে ... এটিকে আবার গুলি করা হয়েছে, তবে, গুলি চালানোর পরে, dragleaveইভেন্টটি কেবলমাত্র শিশু বামের জন্য চালানো হয়েছে, সুতরাং আবার removeClassনির্দেশটি কার্যকর করা হয়েছে
Hristo

আমি সংজ্ঞা দিতে পারি না dragleave কেবল #dropzone... এর জন্য যদি আমি পারতাম তবে আমার এই সমস্যাটি হবে না।
হিস্তো

না, আমি বোঝাতে চাইছি বাচ্চাদের ড্র্যাগেভের জন্য ইভেন্টগুলি যুক্ত করবেন না।
অলিভার

4

এই উত্তরে যেমন বেনার উল্লেখ করেছেন , আপনি শিশু নোডগুলিকে ইভেন্টগুলিতে গুলি চালাতে বাধা দিতে পারেন, তবে যদি আপনাকে কিছু ইভেন্টের সাথে আবদ্ধ করার প্রয়োজন হয় তবে এটি করুন:

#dropzone.dragover *{
   pointer-events: none;
}

এবং এটি আপনার জেএস কোডে যুক্ত করুন:

$("#dropzone").on("dragover", function (event) {
   $("#dropzone").addClass("dragover");
});

$("#dropzone").on("dragleave", function (event) {
   $("#dropzone").removeClass("dragover");
});

2
আমার জন্য ক্রমাগত ওভারলে ফ্ল্যাশিংয়ের ফলাফল।
আন্দ্রে মিখায়লোভ - লোলমাস

3

আপনি যদি jQuery ব্যবহার করেন তবে এটি পরীক্ষা করে দেখুন: https://github.com/dancork/jquery.event.dragout

এটা সত্যিই দুর্দান্ত।

সত্যিকারের ড্রাগলিভ কার্যকারিতা পরিচালনা করতে বিশেষ ইভেন্ট তৈরি করা হয়েছে।

এইচটিএমএল 5 ড্রাগলেভ ইভেন্টটি মাউসআউটের মতো আরও কাজ করে। এই প্লাগইনটি টানতে টানতে মাউসলেভ স্টাইলের কার্যকারিতাটির প্রতিলিপি তৈরি করার জন্য তৈরি হয়েছিল।

ব্যবহারের উদাহরণ:

$ ('# মাইলেমেন্ট')। on ('ড্রাগআউট', ফাংশন (ইভেন্ট) {// আপনার কোড});

সম্পাদনা: আসলে, আমি মনে করি না যে এটি jQuery এর উপর নির্ভরশীল, আপনি সম্ভবত কোডটি এটি না করেই ব্যবহার করতে পারেন।


কি দারুন! ড্র্যাগআউট হ'ল এমন একটি জিনিস যা dragleaveআমি পিতা-মাতা ড্রপজোন ছাড়েনি যদিও প্রচুর পরিমাণে শিশু উপাদানগুলিকে গুলি ছড়িয়ে দিয়ে আমার লেআউটটির জন্য কাজ করেছিল ।
মার্ক কাসন

এই সমস্যাটির সাথে শেষ ঘন্টা ধরে লড়াই করার পরে, dragoutআমার পক্ষে কাজ করা একমাত্র সমাধান।
জেসন হ্যাজেল

2

@ ক্রিস্টো আমার কাছে আরও একটি মার্জিত সমাধান রয়েছে। এটি যদি আপনি ব্যবহার করতে পারেন এমন কিছু হয় তা পরীক্ষা করুন।

আপনার প্রচেষ্টা সব পরে নষ্ট হয়নি। আমি প্রথমে আপনার ব্যবহার করতে সক্ষম হয়েছি তবে এফএফ, ক্রোমে বিভিন্ন সমস্যা ছিল। অনেক ঘন্টা ব্যয় করার পরেও আমি সেই পরামর্শটি পেয়েছি ঠিক যেমনটি ঠিক তেমন কাজ করে।

বাস্তবায়ন কীভাবে হয় তা এখানে। আমি ড্রপ অঞ্চল সম্পর্কে ব্যবহারকারীদের সঠিকভাবে গাইড করতে ভিজ্যুয়াল সংকেতগুলিরও সদ্ব্যবহার করেছি।

$(document).on('dragstart dragenter dragover', function(event) {    
    // Only file drag-n-drops allowed, http://jsfiddle.net/guYWx/16/
    if ($.inArray('Files', event.originalEvent.dataTransfer.types) > -1) {
        // Needed to allow effectAllowed, dropEffect to take effect
        event.stopPropagation();
        // Needed to allow effectAllowed, dropEffect to take effect
        event.preventDefault();

        $('.dropzone').addClass('dropzone-hilight').show();     // Hilight the drop zone
        dropZoneVisible= true;

        // http://www.html5rocks.com/en/tutorials/dnd/basics/
        // http://api.jquery.com/category/events/event-object/
        event.originalEvent.dataTransfer.effectAllowed= 'none';
        event.originalEvent.dataTransfer.dropEffect= 'none';

         // .dropzone .message
        if($(event.target).hasClass('dropzone') || $(event.target).hasClass('message')) {
            event.originalEvent.dataTransfer.effectAllowed= 'copyMove';
            event.originalEvent.dataTransfer.dropEffect= 'move';
        } 
    }
}).on('drop dragleave dragend', function (event) {  
    dropZoneVisible= false;

    clearTimeout(dropZoneTimer);
    dropZoneTimer= setTimeout( function(){
        if( !dropZoneVisible ) {
            $('.dropzone').hide().removeClass('dropzone-hilight'); 
        }
    }, dropZoneHideDelay); // dropZoneHideDelay= 70, but anything above 50 is better
});

স্কোপ ভেরিয়েবলের বাইরে আপনি সংজ্ঞাটি অনুপস্থিত বলে মনে করছেন, আমি ধরে নিইvar dropZoneHideDelay=70, dropZoneVisible=true;
টিমো হুভিনেন

@ টিমো হুওভিনেন হ্যাঁ, ঠিক আছে। আমার বাস্তবায়নে dropZoneHideDelay, dropZoneVisibleদুটি 'on'ডকুমেন্ট ইভেন্ট জুড়ে উভয়েরই প্রয়োজন ।
ভিজিট করুন

2

আমার দুটি সেন্ট: আপনার ড্রপজোনের উপরে একটি স্তর লুকান তারপরে আপনি ড্রেজেন্টার করার সময় এটিটি দেখান, এবং তার উপর ড্র্যাগলেভে লক্ষ্যবস্তু করুন।

ডেমো: https://jsfiddle.net/t6q4shat/

এইচটিএমএল

<div class="drop-zone">
  <h2 class="drop-here">Drop here</h2>
  <h2 class="drop-now">Drop now!</h2>
  <p>Or <a href="#">browse a file</a></p>
  <div class="drop-layer"></div>
</div>

সিএসএস

.drop-zone{
  padding:50px;
  border:2px dashed #999;
  text-align:center;
  position:relative;
}
.drop-layer{
  display:none;
  position:absolute;
  top:0;
  left:0;
  bottom:0;
  right:0;
  z-index:5;
}
.drop-now{
  display:none;
}

জাতীয়

$('.drop-zone').on('dragenter', function(e){
    $('.drop-here').css('display','none');
    $('.drop-now').css('display','block');
    $(this).find('.drop-layer').css('display','block');
    return false;
});

$('.drop-layer').on('dragleave', function(e){
    $('.drop-here').css('display','block');
    $('.drop-now').css('display','none');
    $(this).css('display','none');
    return false;
});

সহজ এবং কার্যকর! আমি স্টপপ্রোগেশন () রুটে যাচ্ছিলাম এবং আমি সমস্ত বাচ্চার ক্ষেত্রে ইভেন্ট হ্যান্ডলারটি প্রয়োগ করতে পছন্দ করি না। এটি অগোছালো মনে হলেও এটি কার্যকরভাবে কার্যকর হয় এবং এটি কার্যকর করা সহজ। ভাল ধারণা.
জন ক্যাটমুল

1

সুতরাং আমার জন্য পদ্ধতির pointer-events: none;খুব ভাল কাজ হয়নি ... সুতরাং এখানে আমার বিকল্প সমাধান:

    #dropzone {
        position: relative;
    }

    #dropzone(.active)::after {
        position: absolute;
        top: 0;
        right: 0;
        bottom: 0;
        left: 0;
        content: '';
    }

এইভাবে dragleaveপিতামাতার পক্ষে সম্ভব নয় (কোনও সন্তানের উপর) বাdragover কোনও শিশু উপাদান সম্ভব নয়। আশাকরি এটা সাহায্য করবে :)

আমি যখন dragenterবা '.এ্যাকটিভ'-ক্লাস যুক্ত করি তখন dragleave। আপনি যদি কাজ না করে থাকেন তবে ক্লাসটি ছেড়ে যান।


1
আমি এটি একটি এমবারজেএস ডি অ্যান্ড ডি উপাদান ব্যবহার করে চেষ্টা করেছি এবং প্রোগ্রামটিমেটিকভাবে 'অ্যাক্টিভ' ক্লাস যুক্ত করা মাউস পিতামহী ডিভের (এমবার-ভিউ) প্রবেশের প্রায় 40% সময় খুব ধীর। নিশ্চিত কেন। তবে এটিকে ছেড়ে দিয়ে এটি দুর্দান্ত কাজ করে, তাই এই সহজ সমাধানের জন্য আপনাকে ধন্যবাদ। সাফারি, ক্রোম, ফায়ারফক্সের সর্বশেষ সংস্করণে (আজকের হিসাবে) একটি ম্যাকের পরীক্ষিত।
আরএমচারি

1

এর জন্য সুপার সিম্পল কুইক ফিক্স, ব্যাপকভাবে পরীক্ষা করা হয়নি তবে এখনই ক্রোমে কাজ করে।

কফিসিপিটি ক্ষমা করুন।

  dragEndTimer = no

  document.addEventListener 'dragover', (event) ->
    clearTimeout dragEndTimer
    $('body').addClass 'dragging'
    event.preventDefault()
    return no

  document.addEventListener 'dragenter', (event) ->
    $('section').scrollTop(0)
    clearTimeout dragEndTimer
    $('body').addClass 'dragging'

  document.addEventListener 'dragleave', (event) ->
    dragEndTimer = setTimeout ->
      $('body').removeClass 'dragging'
    , 50

এটি ক্রোম ফ্লিকার বাগ বা কমপক্ষে এটির ক্রমটি সমাধান করে যা আমাকে সমস্যার কারণ হতে পারে।


1

এই উত্তরটি এখানে পাওয়া যাবে:

এইচটিএমএল 5 ড্রাগলেভ যখন কোনও শিশু উপাদানকে ঘুরে বেড়াচ্ছে তখন তা নিক্ষেপ করা হয়েছে

var counter = 0;

$('#drop').bind({
    dragenter: function(ev) {
        ev.preventDefault(); // needed for IE
        counter++;
        $(this).addClass('red');
    },

    dragleave: function() {
        counter--;
        if (counter === 0) { 
            $(this).removeClass('red');
        }
    }
});

1

আমার সংস্করণ:

$(".dropzone").bind("dragover", function(e){
    console.log('dragover');
});

$(".dropzone").bind("dragleave", function(e) {
  var stopDrag = false;
  if (!e.relatedTarget) stopDrag = true;
  else {
    var parentDrop = $(e.relatedTarget).parents('.dropzone');
    if (e.relatedTarget != this && !parentDrop.length) stopDrag = true;
  }

  if (stopDrag) {
    console.log('dragleave');
  }
});

এই বিন্যাস সহ:

<div class="dropzone">
  <div class="inner-zone">Inner-zone</div>
</div>

আমি উপাদান ক্লাস একটি ডাম্প তৈরি করেছি e.target, e.currentTarget, e.relatedTargetউভয়ের জন্য dragoverএবংdragleave ইভেন্ট নেই।

এটি আমাকে দেখিয়েছে যে প্যারেন্ট ব্লক ছাড়ার সময় (.dropzone ) e.relatedTargetএই ব্লকের কোনও শিশু নয় তাই আমি জানি যে আমি ড্রপজোন থেকে বাইরে আছি।


0

এখানে, সহজ সমাধানগুলির মধ্যে একটি ● ︿ ● ●

এই ঝাঁকুনি একবার দেখুন <- বাক্সের ভিতরে কিছু ফাইল টেনে আনার চেষ্টা করুন

আপনি এর মতো কিছু করতে পারেন:

var dropZone= document.getElementById('box');
var dropMask = document.getElementById('drop-mask');


dropZone.addEventListener('dragover', drag_over, false);
dropMask.addEventListener('dragleave', drag_leave, false);
dropMask.addEventListener('drop', drag_drop, false);

এর মাধ্যমে আপনার এখানে ইতিমধ্যে কী ঘটছে তা জানতে হবে।
শুধু খেয়াল রাখুন, আপনি জানেন।


0

আমারও একই রকম সমস্যা হয়েছে এবং আমি এটিকে এটি ঠিক করেছি:

সমস্যা: ব্যবহারকারী যখন "ড্রপ জোন" (উল উপাদান) তে একটি উপাদান ফেলে দেয় তখন ফাংশন ড্রপ (ev) নিক্ষেপ করা হয়, তবে দুর্ভাগ্যক্রমে, যখন উপাদানটি তার শিশুদের মধ্যে একটিতে ফেলে দেওয়া হয় (লি উপাদানগুলি)।

ঠিক করা:

function drop(ev) { 
ev.preventDefault(); 
data=ev.dataTransfer.getData('Text'); 
if(ev.target=="[object HTMLLIElement]")  
{ev.target.parentNode.appendChild(document.getElementById(data));}
else{ev.target.appendChild(document.getElementById(data));} 
} 

0

আমি নিজে একটি ফাইল আপলোড বাক্সের জন্য এটি প্রয়োগ করার চেষ্টা করছিলাম যেখানে ব্যবহারকারীরা কোনও ফাইল স্পেসে টেনে আনলে বাক্সের রঙ পরিবর্তন হবে।

আমি একটি সমাধান পেয়েছি যা জাভাস্ক্রিপ্ট এবং সিএসএসের একটি দুর্দান্ত মিশ্রণ। বলুন আপনার divআইডি সহ একটি ড্রপযোগ্য জোন রয়েছে #drop। এটি আপনার জাভাস্ক্রিপ্টে যুক্ত করুন:

$('#drop').on('dragenter', function() {
    $(this).addClass('dragover');
    $(this).children().addClass('inactive');
});

$('#drop').on('dragleave', function() {
    $(this).removeClass('dragover');
    $(this).children().removeClass('inactive');
});

তারপরে, আপনার সিএসএসে এটি যুক্ত করুন, সমস্ত বাচ্চাকে শ্রেণিবদ্ধ করতে নিষ্ক্রিয় করতে .inactive:

#drop *.inactive {
    pointer-events: none;
}

সুতরাং, ব্যবহারকারী যতক্ষণ না বাক্সের উপরে উপাদানটি টানছে ততক্ষণ শিশু উপাদানগুলি নিষ্ক্রিয় থাকবে।


0

আমি এখানে উপস্থাপিত কোনও কাজের ক্ষেত্রে সন্তুষ্ট বোধ করিনি, কারণ আমি বাচ্চাদের উপাদানগুলির উপর নিয়ন্ত্রণ হারাতে চাই না।

সুতরাং আমি একটি ভিন্ন যুক্তিযুক্ত পদ্ধতির ব্যবহার করেছি, এটি jQuery প্লাগইনে অনুবাদ করে, যার নাম jquery-ড্রাগহ্যান্ডলার । উচ্চ পারফরম্যান্সের গ্যারান্টি দিয়ে এটি ডিওএমকে পুরোপুরি হেরফের করে না। এর ব্যবহার সহজ:

$(document).ready(function() {

    $(selector).draghandler({
        onDragEnter: function() {
            // $(this).doSomething();
        },
        onDragLeave: function() {
            // $(this).doSomethingElse();
        }
    });

});

এটি কোনও ডিওএম কার্যকারিতা নিয়ে আপস না করে সমস্যার নির্বিঘ্নে মোকাবেলা করে।

ডাউনলোড, বিবরণ এবং তার উপর ব্যাখ্যা গীত সংগ্রহস্থলের


আমি কীভাবে আপনার প্লাগ ইনটিতে ড্রাগ টানুন ইভেন্টটি পেতে পারি?
উডি

আমি আসলে আপনার নির্দেশকে পরীক্ষা করে দেখিনি, তবে আমি মনে করি যে পিতামন্ডল (এ) আসলে (বি) জন্য যাচাই করতে চান সেই উপাদানটিকে ঘিরে না রাখলে এটি কার্যকর হয় না। উদাহরণস্বরূপ, যদি বি এর নীচের প্রান্ত এবং এ এর ​​নীচের প্রান্তের মধ্যে কোনও প্যাডিং না থাকে, তবে ড্রেজেন্টারটি কখনই উপাদান এ এর ​​জন্য বরখাস্ত করা হবে না, তাই না?
মার্সেলজ

@ মার্সেলজ এলিমেন্ট নিজেই বডি ডকুমেন্ট হতে পারে, তাই আপনার ন্যূনতম প্যাডিং সহ আশেপাশের উপাদানগুলির (দেহ কাজ করে না) দরকার নেই। এই পদ্ধতির পরে আমি সীমাবদ্ধতাটি খুঁজে পেয়েছি হ'ল আপনি যদি frameএর সাথে কাজ করেন এবং আপনার উপাদানটি এর সীমানায় থাকে। সেক্ষেত্রে আমি এই পদ্ধতির পরামর্শ দিচ্ছি না।
লুকা ফাগিওলি

0

আমি আসলে যা দেখছি তা পছন্দ করছি Https://github.com/lolmaus/jquery.dragbetter/কিন্তু একটি সম্ভাব্য বিকল্প শেয়ার করতে চেয়েছিলেন। আমার সাধারণ কৌশলটি ছিল ড্রপজোন বা তার কোনও শিশুকে (বুদবুদ দিয়ে) ড্রেজেন্ট করার সময় একটি পটভূমি শৈলী প্রয়োগ করা। তারপরে ড্রপ জোনটি ড্র্যাগে করার সময় আমি শৈলীটি সরিয়ে ফেলি। আইডিয়াটি কোনও সন্তানের দিকে যাওয়ার সময় ছিল, এমনকি যদি আমি ড্রপজোনটি ছেড়ে যাওয়ার সময় শৈলীটি সরিয়ে ফেলি (ড্রাগেলওয়ে ফায়ারগুলি), আমি কোনও শৈশবকে ড্রেজেটারেটিংয়ের সময় পিতা-মাতা ড্রপজোনকে কেবল স্টাইলটি পুনরায় প্রয়োগ করব। অবশ্যই সমস্যাটি হ'ল ড্রপজোন থেকে কোনও ড্রপজোনের সন্তানের দিকে যাওয়ার সময়, ড্র্যাগেভের আগে ড্রেজেটার বাচ্চার উপর গুলি ছোঁড়ে, তাই আমার শৈলীগুলি কার্যকর না হয়ে যায়। আমার জন্য সমাধানটি ছিল ড্রেজেন্টার ইভেন্টটিকে বার্তার কাতারে ফিরিয়ে দেওয়ার জন্য একটি টাইমার ব্যবহার করা, আমাকে ড্র্যাগলেভের পরে এটি প্রক্রিয়া করার অনুমতি দেয়। টাইমার কলব্যাকে ইভেন্টটি অ্যাক্সেস করতে আমি একটি ক্লোজার ব্যবহার করেছি।

$('.dropzone').on('dragenter', function(event) {
  (function (event) {
    setTimeout(function () {
      $(event.target).closest('.dropzone').addClass('highlight');
    }, 0);
  }) (event.originalEvent); 
});

এটি ক্রোমে কাজ করে বলে মনে হচ্ছে, যেমন ফায়ারফক্স এবং ড্রপ জোনে বাচ্চার সংখ্যা নির্বিশেষে কাজ করে। ঘটনাগুলির পুনরায় সন্ধানের গ্যারান্টি দেওয়ার সময়সীমা সম্পর্কে আমি কিছুটা অস্বস্তি বোধ করছি তবে আমার ব্যবহারের ক্ষেত্রে এটি বেশ ভালভাবে কাজ করছে বলে মনে হচ্ছে।


0

আমি নিজে এটিকে বাস্তবায়নের চেষ্টা করছিলাম এবং আমি জ্যাকুরি বা কোনও প্লাগইন চাইনি।

আমি ফাইল আপলোডটি পরিচালনা করতে চেয়েছি, আমার পক্ষে সর্বোত্তম বলে মনে করা:

ফাইল কাঠামো:

--- / আপলোডগুলি {আপলোড ডিরেক্টরি}

--- /js/slyupload.js {জাভাস্ক্রিপ্ট ফাইল।}

--- index.php

--- upload.php

--- styles.css {একটু স্টাইলিং ..

এইচটিএমএল কোড:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
<title>my Dzone Upload...</title>
<link rel="stylesheet" href="styles.css" />
</head>

<body>
    <div id="uploads"></div>        
    <div class="dropzone" id="dropzone">Drop files here to upload</div>     
    <script type="text/javascript" src="js/slyupload.js"></script>      
</body>
</html>

তারপরে এটি সংযুক্ত জাভাস্ক্রিপ্ট ফাইল :: 'জেএস / স্লিপলোড.জেএস'

<!-- begin snippet:  -->

<!-- language: lang-js -->

    // JavaScript Document

    //ondragover, ondragleave...


    (function(){        

        var dropzone = document.getElementById('dropzone');
        var intv;

        function displayUploads(data){
            //console.log(data, data.length);
            var uploads = document.getElementById('uploads'),anchor,x;

            for(x=0; x < data.length; x++){

                //alert(data[x].file);
                anchor = document.createElement('a');
                anchor.href = data[x].file;
                anchor.innerText = data[x].name;

                uploads.appendChild(anchor);
            }               
        }

        function upload(files){
            //console.log(files);
            var formData = new FormData(), 
                xhr      = new XMLHttpRequest(),    //for ajax calls...
                x;                                  //for the loop..

                for(x=0;x<files.length; x++){
                    formData.append('file[]', files[x]);

                    /*//do this for every file...
                    xhr = new XMLHttpRequest();

                    //open... and send individually..
                    xhr.open('post', 'upload.php');
                    xhr.send(formData);*/
                }

                xhr.onload = function(){
                    var data = JSON.parse(this.responseText);   //whatever comes from our php..
                    //console.log(data);
                    displayUploads(data);

                    //clear the interval when upload completes... 
                    clearInterval(intv);
                }                   

                xhr.onerror = function(){
                    console.log(xhr.status);
                }

                //use this to send all together.. and disable the xhr sending above...

                //open... and send individually..
                intv = setInterval(updateProgress, 50);
                xhr.open('post', 'upload.php');
                xhr.send(formData);

                //update progress... 
                 /* */                   
        }

        function updateProgress(){
            console.log('hello');
         }          

        dropzone.ondrop = function(e){
            e.preventDefault(); //prevent the default behaviour.. of displaying images when dropped...
            this.className = 'dropzone';
            //we can now call the uploading... 
            upload(e.dataTransfer.files); //the event has a data transfer object...
        }

        dropzone.ondragover = function(){
            //console.log('hello');
            this.className = 'dropzone dragover';
            return false;
        }

        dropzone.ondragleave = function(){
            this.className = 'dropzone';
            return false;
        }           
    }(window));

সিএসএস:

body{
	font-family:Arial, Helvetica, sans-serif; 
	font-size:12px;
}

.dropzone{
	width:300px; 
	height:300px;
	border:2px dashed #ccc;
	color:#ccc;
	line-height:300px;
	text-align:center;
}

.dropzone.dragover{
	border-color:#000;
	color:#000;
}


0

দুঃখিত এটি জাভাস্ক্রিপ্ট jquery নয়, তবে আমার জন্য এটি সমাধানের সবচেয়ে যুক্তিযুক্ত উপায়। ব্রাউজারটি ড্রোপেনভেকে (পূর্ববর্তী উপাদানটির) ড্রপেনটারের আগে কল করা উচিত (নতুন উপাদানটি প্রকাশ করুন, কারণ ফোর্স্ট জিনিসটি উত্তোলনের আগে অন্য কোনও কিছু প্রবেশ করতে পারে না, কারণ তারা কেন এটি করেছে তা আমি বুঝতে পারি না! সুতরাং আপনাকে কেবল বিলম্ব করার প্রয়োজন ডি ড্রপওয়েভ এর মতো:

function mydropleave(e)
{
    e.preventDefault();
    e.stopPropagation();

    setTimeout(function(e){ //the things you want to do },1);
}

আর ড্রপেন্টারটি হবে ড্রপলেভের পরে, এটাই!


-1

greedy : trueএকটি ফাংশন হিসাবে শিশুকে ব্যবহার করুন droppable। তারপরে প্রথম ইভেন্টটিতে ক্লিক করা ইভেন্টটি শুরু করুন।

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.