JQuery .closest () এর মতো কিন্তু ট্র্যাভারসিং বংশধরদের মতো?


123

jQuery .closest()বংশধরদের অনুসরণ করতে এবং কেবল নিকটস্থদের ফিরে পাওয়ার জন্য কি এর মতো কোনও ফাংশন রয়েছে?

আমি জানি যে .find()ফাংশন আছে, তবে এটি সমস্ত সম্ভাব্য ম্যাচগুলি ফিরিয়ে দেয়, নিকটতম নয়।

সম্পাদনা:

এখানে নিকটতমের সংজ্ঞা দেওয়া হয়েছে (কমপক্ষে আমার জন্য) :

প্রথম স্থানে সমস্ত বাচ্চা ট্র্যাভারড হয়, তারপরে প্রতিটি ব্যক্তি বাচ্চাদের ট্র্যাভার করা হয়।

নীচে দেওয়া উদাহরণস্বরূপ id='2'নিকটতম .closestবংশধরগণid="find-my-closest-descendant"

<div id="find-my-closest-descendant">
    <div>
        <div class="closest" Id='1'></div>
    </div>
    <div class="closest" Id='2'></div>
</div>

দয়া করে জেফফিল লিঙ্কটি দেখুন



@ শ্যাডো উইজার্ড ভালভাবে যদি এটি গভীরতার সাথে প্রথম ট্র্যাভারসাল করে তবে ফলাফল তালিকার শূন্যতম উপাদানটি "নিকটতম" এর অর্থের উপর নির্ভর করে "নিকটতম" নাও হতে পারে।
পয়েন্টি

@ পয়েন্টি কি এটি :firstফিল্টারের মতো নয়?
শেডো উইজার্ড আপনার পক্ষে কান

না, আমি এটি মনে করি না - বিষয়টি হ'ল ": প্রথম" এবং ".eq (0)" ডোম ক্রমটি উল্লেখ করে তবে "নিকটতম" এর অর্থ যদি "সর্বাধিক ডোম নোড দূরে" থাকে তবে এর "নাতি" নির্বাচিতের সাথে মেলে এমন কোনও "সন্তানের" পরিবর্তে প্রথম শিশুটি ফিরে আসবে। আমি ১০০% নিশ্চিত নই যে ওপি অবশ্যই এটির বিষয়ে।
পয়েন্টটি

1
একটি jQuery প্লাগইন রয়েছে যা আপনার জন্য হুবহু এটি করে: প্লাগইনস.জকোয়ারি
টিলিন্ডিগ

উত্তর:


44

আপনার সংজ্ঞা অনুসারে closest, আমি নিম্নলিখিত প্লাগইনটি লিখেছি:

(function($) {
    $.fn.closest_descendent = function(filter) {
        var $found = $(),
            $currentSet = this; // Current place
        while ($currentSet.length) {
            $found = $currentSet.filter(filter);
            if ($found.length) break;  // At least one match: break loop
            // Get all children of the current set
            $currentSet = $currentSet.children();
        }
        return $found.first(); // Return first match of the collection
    }    
})(jQuery);

3
JQuery .closest()ফাংশন থেকে পৃথক, এটি সেই উপাদানটির সাথে মেলে যা এটি বলা হয়েছিল। আমার jsfiddle দেখুন । এটিকে পরিবর্তন করে $currentSet = this.children(); // Current placeএর পরিবর্তে শিশুদের সাথে শুরু করা হবে jsfiddle
allicarn

21
জিকুয়েরির নিকটতম () এছাড়াও বর্তমান উপাদানটির সাথে মিলিত হতে পারে।
ডেভিড হরভথ

120

যদি "নিকটতম" বংশধর দ্বারা আপনি প্রথম সন্তানের অর্থ বোঝাতে পারেন তবে আপনি এটি করতে পারেন:

$('#foo').find(':first');

বা:

$('#foo').children().first();

অথবা, কোনও নির্দিষ্ট উপাদানের প্রথম উপস্থিতি সন্ধানের জন্য, আপনি এটি করতে পারেন:

$('#foo').find('.whatever').first();

বা:

$('#foo').find('.whatever:first');

সত্যই যদিও, আমাদের "নিকটতম বংশধর" এর অর্থ কী এর একটি দৃ definition় সংজ্ঞা দরকার।

যেমন

<div id="foo">
    <p>
        <span></span>
    </p>
    <span></span>
</div>

কোনটি <span>হবে $('#foo').closestDescendent('span')আসতে?


1
বিস্তারিত উত্তরের জন্য 999 টি ধন্যবাদ, আমার অগ্রগতির প্রত্যাশাটি হ'ল প্রথমে সমস্ত বাচ্চা বিভ্রান্ত হয়, তারপরে প্রতিটি ব্যক্তি শিশু হয়। উদাহরণস্বরূপ, আপনি দিয়েছেন, দ্বিতীয় স্প্যানটি ফিরে আসবে
মামু

8
তাই শ্বাস-প্রশ্বাসের প্রথম, গভীরতা-প্রথম নয়
জেসিউইউিং

1
দুর্দান্ত উত্তর। আমি জানতে $('#foo').find('.whatever').first();" আগ্রহী প্রথম" বা "গভীরতা প্রথম" কিনা জানতে আগ্রহী
কলিন

1
এই সমাধানটির সাথে একটি সমস্যা হ'ল jQuery সমস্ত মিলের মানদণ্ড খুঁজে বের করবে এবং তারপরে প্রথমটি ফিরে আসবে। সিজল ইঞ্জিনটি দ্রুত থাকা অবস্থায় এটি অতিরিক্ত অপ্রয়োজনীয় অনুসন্ধানের প্রতিনিধিত্ব করে। প্রথম ম্যাচটি খুঁজে পাওয়ার পরে শর্ট সার্কিটের অনুসন্ধান এবং থামানোর কোনও উপায় নেই।
আইসিফ্যান্টভি

এই উদাহরণগুলি সমস্ত গভীরতা-প্রথম বংশধরকে বেছে নেয়, প্রস্থ-প্রথম নয়, সুতরাং এগুলি আসল প্রশ্নটি সমাধান করতে ব্যবহার করা যাবে না। আমার পরীক্ষায় তারা সকলেই প্রথম স্প্যানটি ফিরিয়েছিল, দ্বিতীয়টি নয়।
JrBaconCheez

18

আপনি নির্বাচকটির findসাথে ব্যবহার করতে পারেন :first:

$('#parent').find('p:first');

উপরের রেখাটি <p>এর বংশধরদের মধ্যে প্রথম উপাদানটি আবিষ্কার করবে #parent


2
আমি মনে করি এটিই ওপি চেয়েছিল, কোনও প্লাগইন প্রয়োজন নেই। এটি প্রতিটি নির্বাচিত উপাদানের জন্য নির্বাচিত উপাদানটির বংশধরদের মধ্যে প্রথম মেলানো উপাদান নির্বাচন করবে । সুতরাং আপনার যদি আপনার আসল নির্বাচনের সাথে 4 টি ম্যাচ থাকে তবে আপনি 4 টি ম্যাচ ব্যবহার করে শেষ করতে পারেন find('whatever:first')
রুটিটাইমস

3

এই পদ্ধতির সম্পর্কে কী?

$('find-my-closest-descendant').find('> div');

এই "সরাসরি শিশু" নির্বাচক আমার পক্ষে কাজ করে me


ওপি বিশেষত এমন কিছু জন্য জিজ্ঞাসা করে যা বংশধরদের অনুসরণ করে, যা এই উত্তর দেয় না। এটি একটি ভাল উত্তর হতে পারে, তবে এই বিশেষ প্রশ্নের জন্য নয়।
jumps4fun

@ কেজিলনর্ডিন সম্ভবত এটি কারণ কারণ আমার উত্তর থেকেই প্রশ্নটি সম্পাদিত হয়েছিল। তদুপরি, নিকটতম বংশধরদের সংজ্ঞা এখনও এতটা পরিষ্কার নয়, কমপক্ষে আমার কাছে।
klawipo

আমি অবশ্যই একমত। নিকটতম বংশধর অনেক কিছুই বোঝাতে পারে। এক্ষেত্রে পিতামাতার সাথে আরও সহজ, যেখানে প্রতিটি স্তরে সর্বদা একক পিতা বা মাতা থাকে। এবং আপনি সম্ভাব্য সম্পাদনাগুলি সম্পর্কেও ঠিক বলেছেন। আমি এখন দেখছি যে আমার মন্তব্যটি কোনওভাবেই সহায়ক ছিল না, বিশেষত যেহেতু ইতিমধ্যে একই ধরণের একটি বিবৃতি ছিল।
jumps4fun

1

খাঁটি জেএস সমাধান (ইএস 6 ব্যবহার করে)।

export function closestDescendant(root, selector) {
  const elements = [root];
  let e;
  do { e = elements.shift(); } while (!e.matches(selector) && elements.push(...e.children));
  return e.matches(selector) ? e : null;
}

উদাহরণ

নিম্নলিখিত কাঠামো বিবেচনা:

ডিভ == $ 0
├── ডিভ == $ 1
। ├── ডিভ
│ ├── Div.findme == $ 4
। ├── ডিভ
। └── ডিভ
├── div.findme == $ 2
। ├── ডিভ
। └── ডিভ
└── ডিভ == $ 3
    ├── বিভাগ
    ├── বিভাগ
    └── বিভাগ
closestDescendant($0, '.findme') === $2;
closestDescendant($1, '.findme') === $4;
closestDescendant($2, '.findme') === $2;
closestDescendant($3, '.findme') === null;


এই সমাধানটি কাজ করে, তবে আমি এখানে বিকল্প ES6 সমাধান পোস্ট করেছি ( স্ট্যাকওভারফ্লো.com / a / 55144581 / 2441655 ) যেহেতু আমার পছন্দ নয়: 1) whileপার্শ্ব-প্রতিক্রিয়াযুক্ত অভিব্যক্তি। ২) .matchesমাত্র একটি পরিবর্তে দুটি লাইনে চেকটি ব্যবহার করুন ।
ভেন্রিক্স

1

যদি কেউ খাঁটি জেএস সমাধানের সন্ধান করে (jQuery এর পরিবর্তে ES6 ব্যবহার করছে) তবে আমি এখানে ব্যবহার করছি:

Element.prototype.QuerySelector_BreadthFirst = function(selector) {
    let currentLayerElements = [...this.childNodes];
    while (currentLayerElements.length) {
        let firstMatchInLayer = currentLayerElements.find(a=>a.matches && a.matches(selector));
        if (firstMatchInLayer) return firstMatchInLayer;
        currentLayerElements = currentLayerElements.reduce((acc, item)=>acc.concat([...item.childNodes]), []);
    }
    return null;
};

আরে, আপনার উত্তরটি আমার নজরে আনার জন্য ধন্যবাদ! আপনি ঠিক বলেছেন, আমার নিজের দিকে ফিরে তাকান, মনে হচ্ছে এটি খুব চালাক এবং প্রকৃতপক্ষে বিশ্রী হওয়ার চেষ্টা করছে ( matchesদু'বার দৌড়ানোও আমাকে বেশ খানিকটা আহ্বান জানায় )। আপনার জন্য +1 :)
ccjmne

0

আমি মনে করি যে প্রথমে আপনাকে "নিকটতম" অর্থ কী তা নির্ধারণ করতে হবে। আপনি যদি বংশোদ্ভূত নোডকে প্যারেন্টাল লিঙ্কগুলির তুলনায় স্বল্পতম দূরত অনুসারে আপনার মাপদণ্ডের সাথে মিলে যায়, তবে ": প্রথম" বা ".eq (0)" ব্যবহার করে প্রয়োজনীয়ভাবে কাজ করবে না:

<div id='start'>
  <div>
    <div>
      <span class='target'></span>
    </div>
  </div>
  <div>
    <span class='target'></span>
  </div>
</div>

উদাহরণস্বরূপ, দ্বিতীয় ".মার্জ" <span>উপাদানটি "শুরু" এর "কাছাকাছি" <div>, কারণ এটি কেবলমাত্র পিতামাতার একদম দূরে। যদি আপনি "নিকটতম" বলতে চাইছেন তবে আপনাকে ফিল্টার ফাংশনে ন্যূনতম দূরত্বটি খুঁজে পেতে হবে। একটি jQuery নির্বাচক থেকে ফলাফল তালিকা সর্বদা DOM ক্রমে থাকে।

হতে পারে:

$.fn.closestDescendant = function(sel) {
  var rv = $();
  this.each(function() {
    var base = this, $base = $(base), $found = $base.find(sel);
    var dist = null, closest = null;
    $found.each(function() {
      var $parents = $(this).parents();
      for (var i = 0; i < $parents.length; ++i)
        if ($parents.get(i) === base) break;
      if (dist === null || i < dist) {
        dist = i;
        closest = this;
      }
    });
    rv.add(closest);
  });
  return rv;
};

এটি হ্যাক প্লাগিনটি সাজানোর মতো কারণ এটি ফলাফল অবজেক্টটি তৈরি করে, তবে ধারণাটি হ'ল আপনি খুঁজে পাওয়া সমস্ত মিলের উপাদানগুলির মধ্যে সবচেয়ে ছোট পিতামাতার পথটি খুঁজে পেয়েছেন। এই কোডটি কারণ কারণে ডোম গাছের বাম দিকে উপাদানগুলির প্রতি পক্ষপাতিত্ব করে< ; <=পক্ষপাতদুষ্ট হবে।


0

আমি এটি রান্না করেছি, অবস্থানিক নির্বাচকদের জন্য matchesSelectorএখনও কোনও প্রয়োগকরণ হয়নি (তাদের কেবলমাত্রের চেয়ে বেশি প্রয়োজন ):

ডেমো: http://jsfiddle.net/TL4Bq/3/

(function ($) {
    var matchesSelector = jQuery.find.matchesSelector;
    $.fn.closestDescendant = function (selector) {
        var queue, open, cur, ret = [];
        this.each(function () {
            queue = [this];
            open = [];
            while (queue.length) {
                cur = queue.shift();
                if (!cur || cur.nodeType !== 1) {
                    continue;
                }
                if (matchesSelector(cur, selector)) {
                    ret.push(cur);
                    return;
                }
                open.unshift.apply(open, $(cur).children().toArray());
                if (!queue.length) {
                    queue.unshift.apply(queue, open);
                    open = [];
                }
            }
        });
        ret = ret.length > 1 ? jQuery.unique(ret) : ret;
        return this.pushStack(ret, "closestDescendant", selector);
    };
})(jQuery);

কিছু বাগ রয়েছে যদিও এটি খুব বেশি পরীক্ষা করে নি।


0

রব ডাব্লু এর উত্তর আমার জন্য বেশ কার্যকর হয়নি। আমি এটিকে খাপ খাইয়ে দিয়েছি যা কাজ করে।

//closest_descendent plugin
$.fn.closest_descendent = function(filter) {
    var found = [];

    //go through every matched element that is a child of the target element
    $(this).find(filter).each(function(){
        //when a match is found, add it to the list
        found.push($(this));
    });

    return found[0]; // Return first match in the list
}

আমার কাছে এটি দেখতে হুবহু .find(filter).first(), কেবল ধীর;)
ম্যাথিয়াস সামসেল

হ্যাঁ আপনি ঠিক বলেছেন। আমি যখন তখনও কোডিংয়ে বেশ নতুন ছিলাম আমি এটি লিখেছিলাম। আমি মনে করি আমি এই উত্তরটি
মুছব

0

আমি যদি লক্ষ্যটি নির্বাচকের সাথে মেলে তবে লক্ষ্যটি অন্তর্ভুক্ত করতে আমি নিম্নলিখিতটি ব্যবহার করব:

    var jTarget = $("#doo");
    var sel = '.pou';
    var jDom = jTarget.find(sel).addBack(sel).first();

মার্কআপ:

<div id="doo" class="pou">
    poo
    <div class="foo">foo</div>
    <div class="pou">pooo</div>
</div>

0

এটি একটি পুরানো বিষয় সত্ত্বেও আমি আমার নিকটতম শিশুটিকে বাস্তবায়িত করতে প্রতিরোধ করতে পারিনি। কমপক্ষে ভ্রমণ (প্রথম শ্বাস) দিয়ে প্রথম পাওয়া বংশধরকে বিতরণ করে। একটি হ'ল recursive (ব্যক্তিগত প্রিয়), অন্যটি টু লিস্ট ব্যবহার করে jQquery এক্সটেনশন হিসাবে পুনরাবৃত্তি না করে।

আশা করি কারও উপকার হবে।

দ্রষ্টব্য: পুনরাবৃত্তকারীগুলি স্ট্যাকের ওভারফ্লো হয়ে যায় এবং আমি অন্যটির উন্নতি করি, এখন পূর্ববর্তী উত্তরগুলির সাথে একইভাবে।

jQuery.fn.extend( {

    closestChild_err : function( selector ) { // recursive, stack overflow when not found
        var found = this.children( selector ).first();
        if ( found.length == 0 ) {
            found = this.children().closestChild( selector ).first(); // check all children
        }
        return found;
    },

    closestChild : function( selector ) {
        var todo = this.children(); // start whith children, excluding this
        while ( todo.length > 0 ) {
            var found = todo.filter( selector );
            if ( found.length > 0 ) { // found closest: happy
                return found.first();
            } else {
                todo = todo.children();
            }
        }
        return $();
    },

});  

0

নিম্নলিখিত প্লাগইনটি নবম নিকটতম বংশধরদের প্রদান করে।

$.fn.getNthClosestDescendants = function(n, type) {
  var closestMatches = [];
  var children = this.children();

  recursiveMatch(children);

  function recursiveMatch(children) {
    var matches = children.filter(type);

    if (
      matches.length &&
      closestMatches.length < n
    ) {
      var neededMatches = n - closestMatches.length;
      var matchesToAdd = matches.slice(0, neededMatches);
      matchesToAdd.each(function() {
        closestMatches.push(this);
      });
    }

    if (closestMatches.length < n) {
      var newChildren = children.children();
      recursiveMatch(newChildren);
    }
  }

  return closestMatches;
};

0

আমি একটি অনুরূপ সমাধানের সন্ধান করছিলাম (আমি নিকটস্থ সমস্ত বংশধরদের অর্থাত্ প্রস্থের প্রথমটি চাই + এটি যে স্তরের বিদ্যমান তা নির্বিশেষে সমস্ত ম্যাচ), আমি এখানে যা শেষ করেছি তা এখানে:

var item = $('#find-my-closest-descendant');
item.find(".matching-descendant").filter(function () {
    var $this = $(this);
    return $this.parent().closest("#find-my-closest-descendant").is(item);
}).each(function () {
    // Do what you want here
});

আশা করি এটা কাজে লাগবে.




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