সরাসরি বাচ্চাদের পুনরুদ্ধার করতে ক্যোরিসেক্টরঅল ব্যবহার করা


119

আমি এটি করতে সক্ষম:

<div id="myDiv">
   <div class="foo"></div>
</div>
myDiv = getElementById("myDiv");
myDiv.querySelectorAll("#myDiv > .foo");

অর্থাৎ, myDivক্লাস রয়েছে এমন উপাদানগুলির প্রত্যক্ষ প্রত্যক্ষ বাচ্চাদের আমি সফলভাবে পুনরুদ্ধার করতে পারি .foo

সমস্যাটি হচ্ছে, এটি আমাকে বিরক্ত করে যে আমাকে অবশ্যই #myDivনির্বাচকটিতে অন্তর্ভুক্ত করতে হবে , কারণ আমি myDivউপাদানটিতে কোয়েরি চালাচ্ছি (সুতরাং এটি স্পষ্টতই অপ্রয়োজনীয়)।

আমার ছাড়তে সক্ষম হওয়া উচিত #myDiv, তবে সিলেক্টরটি আইনী বাক্য গঠন নয় যেহেতু এটি একটি দিয়ে শুরু হয় >

কেউ কি জানেন যে কোনও নির্বাচক কীভাবে নির্বাচন করতে পারেন যা নির্বাচকটি চলছে সেই উপাদানটির কেবল প্রত্যক্ষ বাচ্চা পায়?



উত্তরগুলির মধ্যে আপনার যা প্রয়োজন তা পূরণ করেনি? প্রতিক্রিয়া সরবরাহ করুন বা একটি উত্তর নির্বাচন করুন।
রেন্ডি হল

@ ম্যাটশ - আমি আপনার প্রয়োজনের জন্য আরও ভাল (আইএমও) উত্তর যুক্ত করেছি, এটি পরীক্ষা করে দেখুন!
csuwldcat

উত্তর:


85

ভাল প্রশ্ন. যে সময় এটি জিজ্ঞাসা করা হয়েছিল, "সংযুক্তকারী শিকড় অনুসন্ধানগুলি" করার (সার্বজনীন জন রেজিগ যেহেতু বলেছিলেন ) করার সর্বজনীন-প্রয়োগকৃত উপায়টির অস্তিত্ব ছিল না।

এখন স্কোপ সিউডো-ক্লাস চালু হয়েছে। তাই নয় কি সমর্থিত এজ বা IE এর [প্রাক Chrominum] সংস্করণের উপর, কিন্তু ইতিমধ্যে বেশ কয়েক বছর ধরে সাফারি দ্বারা সমর্থিত হয়েছে। এটি ব্যবহার করে আপনার কোডটি হয়ে উঠতে পারে:

let myDiv = getElementById("myDiv");
myDiv.querySelectorAll(":scope > .foo");

নোট করুন যে কোনও কোনও ক্ষেত্রে আপনি এড়ানো .querySelectorAllও ভাল পুরাতন ফ্যাশনযুক্ত DOM API বৈশিষ্ট্যগুলিও ব্যবহার করতে পারেন । উদাহরণস্বরূপ, পরিবর্তে myDiv.querySelectorAll(":scope > *")আপনি কেবল লিখতে পারেন myDiv.children, উদাহরণস্বরূপ।

তা না হলে আপনি এখনো নির্ভর করতে পারে :scope, আমি অন্য উপায় আরো কাস্টম ফিল্টার যুক্তিবিজ্ঞান যোগ ছাড়া আপনার পরিস্থিতি সামাল দিতে মনে করতে পারেন না (যেমন এটি myDiv.getElementsByClassName("foo"), যার .parentNode === myDiv), এবং সম্ভবত না আদর্শ যদি আপনি যে সত্যিই এক কোড পাথ সমর্থন করার জন্য চেষ্টা করছেন ইনপুট হিসাবে একটি নির্বিচারে নির্বাচক স্ট্রিং এবং আউটপুট হিসাবে ম্যাচের তালিকা নিতে চায়! তবে আমার মতো যদি আপনি এই প্রশ্নটি জিজ্ঞাসা করেই গেছেন তবে আপনি "আপনার যা কিছু ছিল একটি হাতুড়ি ছিল" ভেবে আটকে গেলেন তা ভুলে যাবেন না যে ডোম অফারও দেয় বিভিন্ন ধরণের অন্যান্য সরঞ্জাম রয়েছে।


3
myDiv.getElementsByClassName("foo")এটি একইরকম নয় myDiv.querySelectorAll("> .foo"), এটি আরও বেশি myDiv.querySelectorAll(".foo")(যা আসলে পথে কাজ করে) যাতে এটি সমস্ত বংশধরকে .fooঠিক বাচ্চাদের বিপরীতে খুঁজে পায় ।
বোল্টক্লক

ওহ, বিরক্ত! যার অর্থ: আপনি ঠিক বলেছেন। আমি আরও উত্তর পরিষ্কার করে দিতে আমার উত্তর আপডেট করেছি যে এটি ওপির ক্ষেত্রে খুব ভাল নয় one
নাতিভ

এই লিঙ্কটির জন্য ধন্যবাদ (যা এটির অবশ্যই উত্তর দেবে বলে মনে হয়), এবং "সংযুক্তকারী মূলযুক্ত জিজ্ঞাসা" পরিভাষা যুক্ত করার জন্য ধন্যবাদ।
mattsh

1
জন রেসিগ যাকে "সংযুক্তকারী-মূলযুক্ত প্রশ্নগুলি" বলে ডাকে, নির্বাচক 4 এখন তাদের আপেক্ষিক নির্বাচক বলে
বোল্টক্লক

@ অ্যান্ড্রু স্কোপড স্টাইলশিটগুলির (অর্থাত্ <style scoped>) :scopeএই উত্তরে বর্ণিত সিউডো-সিলেক্টরের সাথে কিছুই করার নেই ।
নাটভেডব

124

কেউ কি জানেন যে কোনও নির্বাচক কীভাবে নির্বাচন করতে পারেন যা নির্বাচকটি চলছে সেই উপাদানটির কেবল প্রত্যক্ষ বাচ্চা পায়?

বর্তমান উপাদানটির সাথে "নির্বাচিত" নির্বাচিত লেখার সঠিক উপায়টি হ'ল ব্যবহার করা :scope

var myDiv = getElementById("myDiv");
var fooEls = myDiv.querySelectorAll(":scope > .foo");

যাহোক, ব্রাউজার সমর্থন সীমিত এবং আপনি যদি এটি ব্যবহার করতে চান তবে আপনার একটি শিম দরকার। এই উদ্দেশ্যে আমি scopedQuerySelectorSim তৈরি করেছি


3
এটি উল্লেখ করার মতো যে :scopeঅনুমানটি বর্তমানে একটি "ওয়ার্কিং ড্রাফ্ট" এবং সুতরাং এটি পরিবর্তিত হতে পারে। এটি সম্ভবত / যখন এটি গৃহীত হয় তা এখনও এটির মতো কাজ করবে তবে আমার মতে এটি করার জন্য এটি "সঠিক উপায়" বলে কিছুটা তাড়াতাড়ি।
Zach Lysobey

2
মনে হচ্ছে এটি ইতিমধ্যে
অবনতি হয়েছে

1
3 বছর পরে এবং আপনি আমার গ্লুটাস ম্যাক্সিমাস সংরক্ষণ করুন!
মেহরাদ

5
@ অ্যাড্রিয়ান মাইসা:: স্কোপটি কোথাও ছাড়েনি। আপনি এটি স্কোপযুক্ত বৈশিষ্ট্যের সাথে মিশ্রিত হতে চলেছেন।
BoltClock

6

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

var count = 0;
function queryChildren(element, selector) {
  var id = element.id,
      guid = element.id = id || 'query_children_' + count++,
      attr = '#' + guid + ' > ',
      selector = attr + (selector + '').replace(',', ',' + attr, 'g');
  var result = element.parentNode.querySelectorAll(selector);
  if (!id) element.removeAttribute('id');
  return result;
}

আমি আপনাকে উত্সাহিত আইডিতে কোনও ধরণের টাইমস্ট্যাম্প বা কাউন্টার যুক্ত করার পরামর্শ দেব। Math.random().toString(36).substr(2, 10)একই টোকেনটি একাধিকবার উত্পাদনের জন্য একটি শূন্য-বিহীন (ছোট হলেও) সম্ভাবনা রয়েছে ।
ফ্রিডরিক হামিদি

আমি নিশ্চিত নই যে পুনরায় পুনরায় হ্যাশগুলির প্রতিকূলতাটি সংখ্যাসূচকভাবে দেওয়া হয়, আইডিটি সাময়িকভাবে একটি মিলিসেকেন্ডের ভগ্নাংশের জন্য প্রয়োগ করা হয়, এবং কোনও ডুপকে একই প্যারেন্ট নোডের শিশু হতে হবে - মূলত: সম্ভাবনাগুলি জ্যোতির্বিজ্ঞানযুক্ত। নির্বিশেষে, একটি কাউন্টার যুক্ত করা ভাল মনে হয়।
csuwldcat

আপনি কী বলতে চাইছেন তা নিশ্চিত নন any dupe would need to also be a child of the same parent node, idবৈশিষ্ট্যগুলি ডকুমেন্ট-বিস্তৃত। আপনি ঠিক বলেছেন বৈষম্যগুলি এখনও যথেষ্ট নগন্য, তবে উঁচু রাস্তাটি নেওয়ার জন্য এবং এই কাউন্টারটি যুক্ত করার জন্য আপনাকে ধন্যবাদ :)
ফ্রেডেরিক হামিদি

8
জাভাস্ক্রিপ্ট সমান্তরালভাবে কার্যকর করা হয় না, তাই সম্ভাবনাগুলি আসলে শূন্য।
ডাব্লুজিএইচ

1
@ ডাব্লুজিএইচও বাহ, আমি এটি বিশ্বাস করতে পারি না, আমি একেবারে হতবাক হয়ে গিয়েছি যে আমি এ জাতীয় সরল বিন্দুটি নিয়ে মস্তিষ্ক ফেটে যাব (আমি মজিলায় কাজ করি এবং এই সত্যটি প্রায়শই আবৃত্তি করি, আরও নিদ্রা পেতে হবে! এলওএল)
সিএসওয়াল্ডক্যাট

5

যদি আপনি নিশ্চিতভাবে অবগত হন যে উপাদানটি অনন্য (যেমন আইডির সাথে আপনার কেস):

myDiv.parentElement.querySelectorAll("#myDiv > .foo");

আরও একটি "গ্লোবাল" সমাধানের জন্য: (একটি ম্যাচসিলিটার শিম ব্যবহার করুন )

function getDirectChildren(elm, sel){
    var ret = [], i = 0, l = elm.childNodes.length;
    for (var i; i < l; ++i){
        if (elm.childNodes[i].matchesSelector(sel)){
            ret.push(elm.childNodes[i]);
        }
    }
    return ret;
}

elmআপনার পিতা বা মাতা উপাদানটি কোথায় এবং selআপনার নির্বাচক। পুরোপুরি পাশাপাশি প্রোটোটাইপ হিসাবে ব্যবহার করা যেতে পারে।


@ লাজ্ড এটি প্রশ্নের অংশ নয়।
র্যান্ডি হল

আপনার উত্তরটি "গ্লোবাল" সমাধান নয়। এটিতে সুনির্দিষ্ট সীমাবদ্ধতা রয়েছে যা লক্ষ করা উচিত, তাই আমার মন্তব্য।
lazd

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

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

@ লাজড - মূল প্রশ্নটি অপ্র परिभाषित ফাংশন এবং গ্লোবাল নেমস্পেস ব্যবহার করে। দেওয়া প্রশ্নের জন্য এটি পুরোপুরি সূক্ষ্ম কাজ work যদি আপনি এটি একটি ভাল সমাধান না মনে করেন তবে এটি ব্যবহার করবেন না, বা কোনও সম্পাদনার পরামর্শ দিন। যদি এটি কার্যত ভুল বা স্প্যাম হয়, তবে একটি ডাউনভোট বিবেচনা করুন।
রেন্ডি হল

2

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

যুক্তিটি হ'ল আপনি প্রথমে সমস্ত মিলে যাওয়া বাচ্চাদের নির্বাচন করুন এবং তারপরে যা প্রত্যক্ষ শিশু নয় তাদের ফিল্টার আউট করুন। একটি বাচ্চা হ'ল প্রত্যক্ষ বাচ্চা যদি এর সাথে একই নির্বাচকের সাথে কোনও মিলের অভিভাবক না থাকে।

function queryDirectChildren(parent, selector) {
    const nodes = parent.querySelectorAll(selector);
    const filteredNodes = [].slice.call(nodes).filter(n => 
        n.parentNode.closest(selector) === parent.closest(selector)
    );
    return filteredNodes;
}

আছে HTH!


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

1

আমি এই পরিস্থিতিটি পরিচালনা করার জন্য একটি ফাংশন তৈরি করেছি, ভেবেছিলাম এটি ভাগ করে নেব।

getDirectDecendent(elem, selector, all){
    const tempID = randomString(10) //use your randomString function here.
    elem.dataset.tempid = tempID;

    let returnObj;
    if(all)
        returnObj = elem.parentElement.querySelectorAll(`[data-tempid="${tempID}"] > ${selector}`);
    else
        returnObj = elem.parentElement.querySelector(`[data-tempid="${tempID}"] > ${selector}`);

    elem.dataset.tempid = '';
    return returnObj;
}

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

আমি আইডি অ্যাট্রিবিউটটি ব্যবহার না করার কারণটি হ'ল আইডি বৈশিষ্ট্যটি ইতিমধ্যে ব্যবহৃত হতে পারে এবং আমি এটিকে ওভাররাইড করতে চাই না।


0

ভাল আমরা সহজেই ব্যবহার করে কোনও উপাদানটির প্রত্যক্ষ প্রত্যক্ষ বাচ্চাদের সহজেই পেতে childNodesপারি এবং আমরা একটি নির্দিষ্ট শ্রেণীর সাথে পূর্বপুরুষদের বেছে querySelectorAllনিতে পারি, সুতরাং আমরা কোনও নতুন ফাংশন তৈরি করতে পারি যা উভয়কেই পেয়ে যায় এবং দুটির তুলনা করে imagine

HTMLElement.prototype.queryDirectChildren = function(selector){
  var direct = [].slice.call(this.directNodes || []); // Cast to Array
  var queried = [].slice.call(this.querySelectorAll(selector) || []); // Cast to Array
  var both = [];
  // I choose to loop through the direct children because it is guaranteed to be smaller
  for(var i=0; i<direct.length; i++){
    if(queried.indexOf(direct[i])){
      both.push(direct[i]);
    }
  }
  return both;
}

দ্রষ্টব্য: এটি নোডলিস্ট নয়, নোডের একটি অ্যারে প্রদান করবে।

ব্যবহার

 document.getElementById("myDiv").queryDirectChildren(".foo");

0

আমি যুক্ত করতে চাই যে আপনি কেবলমাত্র বর্তমান নোডের জন্য একটি অস্থায়ী বৈশিষ্ট্য নির্ধারণ করে : স্কোপের সামঞ্জস্যতা বাড়িয়ে তুলতে পারেন ।

let node = [...];
let result;

node.setAttribute("foo", "");
result = window.document.querySelectorAll("[foo] > .bar");
// And, of course, you can also use other combinators.
result = window.document.querySelectorAll("[foo] + .bar");
result = window.document.querySelectorAll("[foo] ~ .bar");
node.removeAttribute("foo");

-1

আমি সাথে যেতে হবে

var myFoo = document.querySelectorAll("#myDiv > .foo");
var myDiv = myFoo.parentNode;

-2

আমি এটি চেষ্টা না করেই এটি করছি। এই কাজ করবে?

myDiv = getElementById("myDiv");
myDiv.querySelectorAll(this.id + " > .foo");

একবার চেষ্টা করে দেখুন, সম্ভবত এটি কাজ করে না। অ্যাপোলোভিস, তবে আমি এটি এখন চেষ্টা করার জন্য কোনও কম্পিউটারে নেই (আমার আইফোন থেকে প্রতিক্রিয়া জানিয়ে)।


3
কিউএসএকে যে উপাদানটি বলা হচ্ছে এটি স্কোপ করা হয়, সুতরাং এটি মাইডিভের মধ্যে অন্য আইডিটি মাইডিভের মতো একই আইডি সহ সন্ধান করবে, তারপরে তার শিশুরা .foo দিয়ে। আপনি `ডকুমেন্ট.কোয়ারীসিলিটরআল ('#' + myDiv.id + '> .foo') এর মতো কিছু করতে পারেন;
সম্ভবত
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.