এইচটিএমএল লেবেল যদি ফায়ারফক্সে ক্লিক করার সময় মাউসটি সরানো হয় তবে সংশ্লিষ্ট ইনপুটটিকে ট্রিগার করবে না


13

নিম্নলিখিত উদাহরণে, আপনি যখন লেবেলে ক্লিক করেন, ইনপুট স্থিতি পরিবর্তন করে।

document.querySelector("label").addEventListener("click", function() {
  console.log("clicked label");
});
label {
  -webkit-user-select: none;
  -moz-user-select: none;
  -ms-user-select: none;
  user-select: none;
}
<input type="checkbox" id="1">
<label for="1">Label</label>

ক্রোম, যখন আপনি মধ্যে কার্সার সরানোর সালে mousedownএবং mouseup, ঘটনা ইনপুট এখনও আলোড়ন সৃষ্টি পরার যেহেতু ফায়ারফক্সে চেকবক্সটি অবস্থা পরিবর্তন করেন না।

এই সমাধানের জন্য একটি উপায় আছে কি? (জাভাস্ক্রিপ্ট ইভেন্ট শ্রোতাদের ব্যবহার না করে)

ফায়ারফক্স সংস্করণ: 69.0.3 (64-bit)

ক্রোম ব্যবহারের সময় সম্পূর্ণ ক্রিয়াকলাপ।

  1. লেবেলের উপর বোতাম টিপুন
  2. বোতামটি ধরে রাখার সময় কার্সারটিকে প্রায় কাছাকাছি নিয়ে যান (এমনকি লেবেলের বাইরেও)
  3. কার্সারটি লেবেলে ফিরিয়ে দিন
  4. বোতামটি ছেড়ে দিন

ক্রোমে, আপনি যখন মোউসডাউন এবং মাউসআপ ইভেন্টগুলির মধ্যে কার্সারটি সরান তখন ইনপুটটি এখনও ট্রিগার হয়ে যায় -> এটি ক্রোমে আমার পক্ষে হয় না এবং ওটি হওয়া উচিত নয়। একটি ক্লিকের = mousedown + + mouseup .. কিছু ধারনা সম্পর্কিত: stackoverflow.com/a/51451218/8620333
Temani আফিফ

@TemaniAfif এখন আপনার কি ক্রোমের ক্ষেত্রে এটি ঘটেছে? (যেহেতু আমি পরিষ্কার করছি যে এটি আমি কী করছি)। বা এটি এখনও চেকবক্সের অবস্থার পরিবর্তন করে না?
নিক জৌম

1
আমরা যদি মাউসটিকে লেবেলের উপরে রাখি তবে ঠিক আছে। পদক্ষেপটি এর প্রভাব ফেলবে না তাই আমি অনুমান করি যে আমরা একটি ফায়ারফক্স বাগের মুখোমুখি
হয়েছি

2
এটি একটি বাগ যা ফিরফক্স বাগ পোর্টালে UNCONFIRMED স্থিতি হিসাবে চিহ্নিত হয়, "একটি" ক্লিক করুন কেবল তখনই ঘটানো উচিত যখন মোউসডাউন এবং মাউসআপ একই জায়গায় থাকত "আপনি সেখানে বাগ url পরীক্ষা করতে পারেন: bugzilla.mozilla.org/show_bug। সিজি? আইডি = 319347
জাদলি

1
@ তেমনিএফ যদি আমি সম্মত হন তবে কার্সারটি সরিয়ে নেওয়াও 1pxইন্টারঅ্যাকশনটি ভেঙে দেবে।
নিক জৌম

উত্তর:


3

ভূমিকা

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

সমাধান - উদাহরণ

var mutationConfiguration = {
  attributes: true,
  childList: true
};

if (document.readyState === "complete") onLoad();
else addEventListener("load", onLoad);

var managingDoms = [];

function onLoad() {
  document.querySelectorAll("label[for]").forEach(manageLabel);
  if (typeof MutationObserver === "function") {
    var observer = new MutationObserver(function(list) {
      list.forEach(function(item) {
        ({
          "attributes": function() {
            if (!(item.target instanceof HTMLLabelElement)) return;
            if (item.attributeName === "for") manageLabel(item.target);
          },
          "childList": function() {
            item.addedNodes.forEach(function(newNode) {
              if (!(newNode instanceof HTMLLabelElement)) return;
              if (newNode.hasAttribute("for")) manageLabel(newNode);
            });
          }
        }[item.type])();
      });
    });
    observer.observe(document.body, mutationConfiguration);
  }
}

function manageLabel(label) {
  if (managingDoms.includes(label)) return;
  label.addEventListener("click", onLabelClick);
  managingDoms.push(label);
}

function onLabelClick(event) {
  if (event.defaultPrevented) return;
  var id = this.getAttribute("for");
  var target = document.getElementById(id);
  if (target !== null) {
    this.removeAttribute("for");
    var self = this;
    target.click();
    target.focus();
    setTimeout(function() {
      self.setAttribute("for", id);
    }, 0);
  }
}
label {
  -webkit-user-select: none;
  -moz-user-select: none;
  -ms-user-select: none;
  user-select: none;
  padding: 10px;
  border: 1px solid black;
  cursor: pointer;
}
<input type="checkbox" id="a">
<input type="text" id="b">
<label for="a">A</label>
<script>
  setTimeout(function() {
    var label = document.createElement("label");
    label.setAttribute("for", "b");
    label.textContent = "b";
    document.body.appendChild(label);
  }, 3E3);
</script>

ব্যাখ্যা

onLabelClick

onLabelClickযখনই কোনও লেবেল ক্লিক করা হবে তখন ফাংশনটি কল করা দরকার, এটি লেবেলের সাথে সম্পর্কিত ইনপুট উপাদান রয়েছে কিনা তা খতিয়ে দেখা হবে। যদি এমন হয়, এটা আরম্ভ হবে, অপসারণ forলেবেল অ্যাট্রিবিউট যাতে ব্রাউজার বাগ ট্রিগার পুনরায় করা হবে না এটা এবং তারপর একটি ব্যবহার হবে না setTimeoutএর 0msযোগ করার জন্য forএট্রিবিউট ফিরে একবার ঘটনা আপ bubbled হয়েছে। এর অর্থ কল event.preventDefaultকরতে হবে না এবং অন্য কোনও ক্রিয়াকলাপ / ইভেন্ট বাতিল হবে না। এছাড়াও যদি আমাকে এই ফাংশনটি ওভাররাইড করার দরকার হয় তবে আমাকে কেবল একটি ইভেন্ট-শ্রোতা যুক্ত করতে হবে Event#preventDefaultযা forগুণটি কল করে বা সরিয়ে দেয় ।

manageLabel

কাজmanageLabelএটি কোনও লেবেল চেক গ্রহণ করে যদি এটি ইতিমধ্যে কোনও ইভেন্ট শ্রোতা যুক্ত হয়ে এটিকে পুনরায় যুক্ত করা এড়াতে যুক্ত করা হয়েছে, শ্রোতা যদি এটি ইতিমধ্যে যুক্ত না করা হয় তবে এটি যোগ করে এবং লেবেলের তালিকায় এটি পরিচালনা করা হয়েছে। পৃষ্ঠাটি লোড হয়ে যাওয়ার

onLoad

পরে ফাংশনটি কল করা onLoadদরকার যাতে manageLabelএই মুহুর্তে ডিওমের সমস্ত লেবেলের জন্য ফাংশনটি কল করা যায়। ফাংশনটি লোডটি সরিয়ে দেওয়ার পরে (এবং স্ক্রিপ্টটি চালানো হয়েছে) যুক্ত হওয়া কোনও লেবেল ধরতে মিউটেশনঅবার্সারও ব্যবহার করে ।

উপরে প্রদর্শিত কোডটি মার্টিন বার্কার দ্বারা অনুকূলিত করা হয়েছিল ।


আপনার কোডটি কিছুটা নির্বিঘ্নে কিছু চেক করা দরকার যা এটির প্রয়োজন হয় না এবং কিছু ব্যয়বহুল সিপিইউ চক্র, আমি এটি আপনার জন্য পেস্টবিন.
com

এটি HTMLLabelElementএইচটিএমলেমেন্ট উভয়ের পরিবর্তে চেকটি প্রতিস্থাপন করে এবং ট্যাগনামটি একটি লেবেল ছিল এমন একটি চেক
বার্কর্ম্ন

চতুর কিন্তু ব্যাপকভাবে জটিল
স্টিভ টমলিন

2

আমি জানি আপনি জেএস ইভেন্টের শ্রোতা চান নি, তবে আমি ভাবছিলাম আপনি যে আন্দোলনটি সনাক্ত করতে চান তা এটি ক্লিক করে না তবে মোসডাউন ব্যবহার করছে (মাউসআপের পরে মাউসাউন)।

ফায়ারফক্সে এটি একটি ত্রুটিযুক্ত ত্রুটিযুক্ত হওয়ার পরেও আপনি মোসডাউন ইভেন্টটি ব্যবহার করে এটি পেতে পারেন

আমাকে আপনার আইডি পরিবর্তন করতে হবে একটি বৈধ আইডি হতে হবে একটি অক্ষর দিয়ে শুরু করতে

document.querySelector("label").addEventListener("mousedown", function(evt) {
  console.log("clicked label");
  // if you want to to check the checkbox when it happens,
  let elmId = evt.target.getAttribute("for")
  let oldState = document.querySelector("#"+elmId).checked;
  setTimeout(() => {
    if(oldState == document.querySelector("#"+elmId).checked){
      document.querySelector("#"+elmId).checked = !oldState;
    }
  }, 150)
});
label {
  -webkit-user-select: none;
  -moz-user-select: none;
  -ms-user-select: none;
  user-select: none;
}
<input type="checkbox" id="valid_1">
<label for="valid_1">Label</label>


সমস্যাটি হ'ল আমাকে এই স্ক্রিপ্টটি querySelectorAllপৃষ্ঠা লোডে (ব্যবহার করে ) চালাতে হবে এবং তারপরে, প্রতিবার ডমটিতে একটি লেবেল যুক্ত করা হবে। আপনি Event#preventDefaultএই বাগ নেই এমন ব্রাউজারগুলিতে ডাবল ক্লিক এড়ানোর জন্য ব্যবহার করার কারণে এটি সাধারণভাবে লেবেলগুলিতে বা ডোমগুলিতে যুক্ত যে কোনও মাউস ইভেন্ট শ্রোতাদের জবাবদিহি করতে পারে। অবশেষে, clickইভেন্টটি ব্যবহার করা আরও ভাল হবে, কারণ এটির উদ্দেশ্যযুক্ত ক্রিয়াকলাপের সাথে একই ইন্টারঅ্যাকশন হবে। তা ছাড়া, এটি এখন পর্যন্ত সেরা উত্তর।
নিক zoum

@ নিকজৌম আমি আপনার preventDefault()সমস্যার সমাধানের জন্য কোডটি আপডেট করেছি , সুতরাং এটি ব্যবহার না করে ব্রাউজারটি এটি পরিবর্তন না করে তা পরিবর্তন করেছে কিনা তা যাচাই করে কাজ করে, 150 এমএসের পরে ব্যবহারকারীর এটি লক্ষ্য না করার জন্য যথেষ্ট দ্রুত এবং ব্রাউজারটি যে কাজ করেছে তা যথেষ্ট ধীর ইনটাইম যদি এটি যা করা উচিত তা করতে চলেছে। এটা কি ভালো?
বার্কর্ম্ন

0

নাহয় এটি আপনার ফায়ারফক্স বাগের মতো দেখাচ্ছে এবং এটি আপনার কোডের কোনও সমস্যা নয়। আমি বিশ্বাস করি না যে এই আচরণের জন্য কোনও সিএসএস কাজ আছে।

আপনি এটি মজিলাকে জানাতে এবং সমস্যাটি স্থির করতে সক্ষম হতে পারেন, তবে আমি তার উপর নির্ভর করব না। https://bugzilla.mozilla.org/home

একটি সম্ভাব্য কাজের জন্য আমি পরিবর্তে মাউসআপ এ ইভেন্টটি ট্রিগার করার পরামর্শ দেব।


0

জাভাস্ক্রিপ্ট ব্যতীত, আপনি যখন তার "জন্য" মান একটি ইনপুট "আইডি" মান হিসাবে লেবেলটি ক্লিক করেন তখন ইনপুটটি ক্লিক হয়ে যায়, তবে এটি ব্রাউজারগুলির মধ্যে সামঞ্জস্যপূর্ণ নয়।

যদি কোনও ব্রাউজার উপরেরটি অনুসরণ করে তবে আপনার জাভাস্ক্রিপ্ট ক্লিক ইভেন্টটি প্রভাবটি বাতিল করবে, যা কিছুই না করে শেষ করে।

একটি সমাধান

ব্রাউজারগুলির মধ্যে ধারাবাহিকতা রাখতে আপনি একটি ভিন্ন কৌশল অবলম্বন করতে পারেন: অন্লোড 'ডেটা-ফর' এর জন্য 'জন্য' সমস্ত বৈশিষ্ট্যকে গতিশীলভাবে পরিবর্তন করে, তাই এটি মূল ব্রাউজারটিকে প্রভাবিত করে। তারপরে আপনি আপনার ক্লিক ইভেন্টটি প্রতিটি লেবেলে প্রয়োগ করতে পারেন।

var replaceLabelFor = function () {
    var $labels = document.querySelectorAll('label');
    var arrLabels = Array.prototype.slice.call($labels);
    arrLabels.forEach(function (item) {
      var att = document.createAttribute('data-for');
      att.value = String(this.for);
      item.setAttributeNode(att);
      item.removeAttribute('for')
    });
}

var applyMyLabelClick() {
  document.querySelector("label").addEventListener("click", function() {
    console.log("clicked label");
  });
}

// x-browser handle onload
document.attachEvent("onreadystatechange", function(){
  if(document.readyState === "complete"){
    document.detachEvent("onreadystatechange", arguments.callee);
    replaceLabelFor();
    applyMyLabelClick();
  }
});

document.attachEvent("onreadystatechange",আমি ঠিক আছি আমি কীভাবে এসেছি তুমি ওটা নিয়ে গিয়েছ না document.addEventListener("DOMContentLoaded",কেন?
বার্কর্ম্ন

এটি কেবল একটি পদ্ধতি যা আমি দেখেছিলাম যা কিছুটা এক্স-ব্রাউজার। আপনি কখন পছন্দ করেন তা চয়ন করুন।
স্টিভ টমলিন

-2

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

Document (দস্তাবেজ) .অন ('ক্লিক', '.item', ফাংশন (ইভেন্ট) {});

অতীতে এই বিষয়টি পড়া থেকে, এটি ফায়ারফক্সের নীচে আপনার ক্রিয়াকে উপাদানটি টেনে আনার প্রয়াস হিসাবে বোঝা গেছে, যেহেতু ব্যবহারকারীর নির্বাচন কোনও নয়, এটি কেবল ডিফল্ট আচরণকে বাধা দেয়।

এটি মোটামুটি সীমাবদ্ধ জ্ঞানের উপর ভিত্তি করে তবে এটি একটি পরিচিত বাগ / চিকিত্সা বলে মনে হচ্ছে এবং এটি সমর্থন করার জন্য কয়েকটি নিবন্ধ রয়েছে।


আমি প্রশ্নে স্পষ্ট করে বলেছি without using JavaScript event listeners
নিক জোউম

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