ট্যাব সূচীতে নেক্সট এলিমেন্টে ফোকাস করুন


109

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

function OnFocusOut()
{
    var currentElement = $get(currentElementId); // ID set by OnFocusIn 

    currentElementId = "";
    currentElement.nextElementByTabIndex.focus();
}

অবশ্যই এটি কাজ করার জন্য পরের এলিমেন্টবাইট্যাবডেক্সটি মূল অংশ। আমি ট্যাব অনুক্রমের পরবর্তী উপাদানটি কীভাবে খুঁজে পাব? সমাধানটি জেএসক্রিপ্ট ব্যবহার করে জিকুয়ের মতো কিছু নয় ভিত্তিক করা দরকার like


4
তোমার এই লাইনটা কেন currentElementId = "";?

4
আমি মনে করি না যে কোনও ব্রাউজারগুলি ট্যাব অর্ডার সম্পর্কিত তথ্য প্রকাশ করে - এবং ব্রাউজারগুলি নিজেরাই ব্যবহৃত অ্যালগরিদমটির অনুলিপি করা খুব জটিল। হতে পারে আপনি আপনার প্রয়োজনীয়তা সীমাবদ্ধ করতে পারেন, যেমন "কেবল বিবেচনা করুন input, buttonএবং textareaট্যাগগুলি এবং tabindexবৈশিষ্ট্যটিকে উপেক্ষা করুন "।
ওলাদিমির প্যালান্ট

আমাদের আপনার .newElementByTabIndexকোডটি দেখতে হবে কারণ এটি কী কাজ করে না।
0x499602D2

4
তারপরে আবার, সম্ভবত নির্দিষ্ট ট্যাগগুলির সীমাবদ্ধতা অপ্রয়োজনীয় - focus()পদ্ধতিটি বিদ্যমান কিনা তা পরীক্ষা করতে পারে ।
ওলাদিমির প্যালান্ট

4
@ ডেভিড এটি ফাংশন যা বিদ্যমান নেই তাই আমার প্রশ্ন। : ডি
জ্যাডজিয়াএমডি

উত্তর:


25

জ্যাকোয়ারি ছাড়াই: প্রথমে আপনার ট্যাব-সক্ষম উপাদানগুলিতে এটি যুক্ত class="tabable"করুন আমাদের সেগুলি পরে নির্বাচন করতে দিন। (নীচের কোডে "।" শ্রেণি নির্বাচক উপসর্গটি ভুলে যাবেন না)

var lastTabIndex = 10;
function OnFocusOut()
{
    var currentElement = $get(currentElementId); // ID set by OnFOcusIn
    var curIndex = currentElement.tabIndex; //get current elements tab index
    if(curIndex == lastTabIndex) { //if we are on the last tabindex, go back to the beginning
        curIndex = 0;
    }
    var tabbables = document.querySelectorAll(".tabable"); //get all tabable elements
    for(var i=0; i<tabbables.length; i++) { //loop through each element
        if(tabbables[i].tabIndex == (curIndex+1)) { //check the tabindex to see if it's the element we want
            tabbables[i].focus(); //if it's the one we want, focus it and exit the loop
            break;
        }
    }
}

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

4
ঠিক আছে, এটি কি কোনও ফর্মের জন্য? উপাদান যদি আপনি চান সব ইনপুট উপাদানের হন, তাহলে আপনি লাইন প্রতিস্থাপন করতে পারেন var tabbables = document.getElementsByName("tabable");সঙ্গে var tabbables = document.getElementsByTagName("input");পরিবর্তে
ব্রায়ান Glaz

var tabbables = document.querySelectorAll("input, textarea, button")// আই 8 +, আপনার এইচটিএমএল সংশোধন না করে সমস্ত ট্যাববেলগুলির জন্য একটি রেফারেন্স পান।
গ্রেগ

4
শ্রেণি = নামের বৈশিষ্ট্যটি ব্যবহার না করে "ট্যাব্বেবল"
ক্রিস এফ ক্যারল

4
নোট করুন যে ফ্লেক্সবক্স ব্যবহার করে উপাদানগুলির ক্রমটি ব্রাউজারের ভিজ্যুয়ালি তুলনায় ডিওএম-এ আলাদা। আপনি যখন ফ্লেক্সবক্স ব্যবহার করে উপাদানগুলির ক্রম পরিবর্তন করেন তখন কেবল পরবর্তী ট্যাবেবল উপাদানটি বাছাই কার্যকর হয় না।
হনিভ

76

আমি এটিকে কখনই বাস্তবায়ন করি নি, তবে আমি একই ধরণের সমস্যাটি দেখেছি এবং আমি কী চেষ্টা করব তা এখানে।

প্রথমে এটি চেষ্টা করুন

প্রথমত, আমি দেখতে পাচ্ছি যে আপনি বর্তমানে যে উপাদানটিতে ফোকাস রেখেছেন তার উপর ট্যাব কীটির জন্য কেবল কোনও keypressইভেন্ট ফায়ার করতে পারেন । বিভিন্ন ব্রাউজারের জন্য এটি করার আলাদা উপায় থাকতে পারে।

যদি এটি কাজ না করে, আপনাকে আরও কঠোর পরিশ্রম করতে হবে ...

JQuery প্রয়োগের উল্লেখ, আপনার অবশ্যই:

  1. ট্যাব এবং শিফট + ট্যাব শুনুন
  2. কোন উপাদানগুলি ট্যাব-সক্ষম তা জেনে নিন
  3. ট্যাব অর্ডার কীভাবে কাজ করে তা বুঝুন

1. ট্যাব এবং শিফট + ট্যাব শুনুন

ট্যাব এবং শিফট + ট্যাব শোনা সম্ভবত ওয়েবে অন্য কোথাও ভালভাবে কভার করা আছে, তাই আমি সেই অংশটি এড়িয়ে যাব।

২. কোন উপাদানগুলি ট্যাব-সক্ষম তা জেনে নিন

কোন উপাদানগুলি ট্যাব-সক্ষম তা জেনে রাখা আরও জটিল। মূলত, কোনও উপাদান ট্যাব-সক্ষম হয় যদি এটি ফোকাসযোগ্য হয় এবং বৈশিষ্ট্য tabindex="-1"সেট না থাকে । সুতরাং আমাদের অবশ্যই জিজ্ঞাসা করতে হবে কোন উপাদানগুলি ফোকাসযোগ্য। নিম্নলিখিত উপাদানগুলি মনোনিবেশযোগ্য:

  • input, select, textarea, button, এবং objectউপাদানের অক্ষম নেই যে।
  • aএবং সেগুলির জন্য যেগুলির areaএকটি hrefবা সংখ্যার মান রয়েছে সেগুলির জন্য tabindex
  • tabindexসেটের জন্য একটি সংখ্যার মান রয়েছে এমন কোনও উপাদান ।

তদুপরি, একটি উপাদান কেবল তখনই ফোকাসযোগ্য যদি:

  • এর পূর্বপুরুষদের কেউ নেই display: none
  • এর কম্পিউটেড মান visibilityহয় visible। এর অর্থ হল যে নিকটতম পূর্বপুরুষটি visibilityসেট করেছেন তার অবশ্যই একটি মান থাকতে হবে visible। যদি কোনও পূর্বপুরুষ visibilityসেট না করে থাকে তবে গণনা করা মান visible

আরও বিশদ অন্য স্ট্যাক ওভারফ্লো উত্তরে

৩. ট্যাব অর্ডার কীভাবে কাজ করে তা বুঝুন

একটি নথিতে উপাদানগুলির ট্যাব tabindexক্রমটি অ্যাট্রিবিউট দ্বারা নিয়ন্ত্রিত হয় । যদি কোনও মান সেট না করা থাকে tabindexতবে কার্যকরভাবে কার্যকর হয় 0

tabindexনথির জন্য অর্ডার: 1, 2, 3, ..., 0।

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


39

এই উদ্দেশ্যে আমি যা কিছু তৈরি করি তা এখানে:

focusNextElement: function () {
    //add all elements we want to include in our selection
    var focussableElements = 'a:not([disabled]), button:not([disabled]), input[type=text]:not([disabled]), [tabindex]:not([disabled]):not([tabindex="-1"])';
    if (document.activeElement && document.activeElement.form) {
        var focussable = Array.prototype.filter.call(document.activeElement.form.querySelectorAll(focussableElements),
        function (element) {
            //check for visibility while always include the current activeElement 
            return element.offsetWidth > 0 || element.offsetHeight > 0 || element === document.activeElement
        });
        var index = focussable.indexOf(document.activeElement);
        if(index > -1) {
           var nextElement = focussable[index + 1] || focussable[0];
           nextElement.focus();
        }                    
    }
}

বৈশিষ্ট্য:

  • ফোকাসযোগ্য উপাদানগুলির কনফিগারযোগ্য সেট
  • কোন jQuery প্রয়োজন
  • সমস্ত আধুনিক ব্রাউজারে কাজ করে
  • দ্রুত এবং লাইটওয়েট

4
এটি সবচেয়ে কার্যকর এবং সংস্থান-বান্ধব সমাধান। ধন্যবাদ! : এখানে আমার সম্পূর্ণ পরিশ্রমী স্ক্রিপ্ট হয় stackoverflow.com/a/40686327/1589669
eapo

সুস্পষ্ট ট্যাবআইন্ডেক্স ফোকাসেবল.সর্ট (সাজ্ট_বি_ট্যাব ইন্ডেক্স)
ডেভবি.সি

4
সেরা ! এটি অবশ্যই জটিল nextElementSiblingহতে পারে : ফোকাসযোগ্য নাও হতে পারে, পরবর্তী ফোকাসযোগ্য কোনও ভাইবোন নাও হতে পারে।
টিনমারিনো

ভাল পদ্ধতির, তবে এটি এমন কোনও ইনপুটের জন্য অনুমতি দেয় যা টাইপ নয় hiddenএবং প্রচ্ছদও রয়েছে textareaএবং select
Lucero

23

আমি একটি সাধারণ jQuery প্লাগইন তৈরি করেছি যা এটি করে this এটি পরবর্তী 'ট্যাবযোগ্য' উপাদানটি খুঁজে পেতে jQuery UI এর ': ট্যাব্বেবল' নির্বাচক ব্যবহার করে এবং এটি নির্বাচন করে।

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

// Simulate tab key when element is clicked 
$('.myElement').bind('click', function(event){
    $.tabNext();
    return false;
});

8

উত্তরের মূলটি পরবর্তী উপাদানটি অনুসন্ধানের উপর নির্ভর করে:

  function findNextTabStop(el) {
    var universe = document.querySelectorAll('input, button, select, textarea, a[href]');
    var list = Array.prototype.filter.call(universe, function(item) {return item.tabIndex >= "0"});
    var index = list.indexOf(el);
    return list[index + 1] || list[0];
  }

ব্যবহার:

var nextEl = findNextTabStop(element);
nextEl.focus();

লক্ষ্য করুন আমি অগ্রাধিকার দেওয়ার বিষয়ে চিন্তা করি না tabIndex


4
যদি ট্যাবিনডেক্স আদেশ ডকুমেন্ট আদেশের বিপরীতে যায়? আমি মনে করি অ্যারেটি টবিনডেক্স নম্বর দিয়ে ডকুমেন্টের অর্ডার অনুসারে বাছাই করতে হবে
ক্রিস এফ ক্যারল

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

যদি এমন কোনও আইটেম যা এই ট্যাগগুলির মধ্যে একটি নয় তবে একটি ট্যাবিনডেক্স বৈশিষ্ট্য রয়েছে?
ম্যাট পেনিংটন

4
@ ম্যাটপেনিংটন এটি উপেক্ষা করা হবে। ফিল্টারটি অনুসন্ধানের গতি বাড়ানোর জন্য (একটি প্রয়াস), মানিয়ে নিতে নির্দ্বিধায়।
আন্দ্রে ওয়ার্ল্যাং

3

উপরে একটি মন্তব্যে উল্লিখিত হিসাবে, আমি মনে করি না যে কোনও ব্রাউজারগুলি ট্যাব অর্ডার সম্পর্কিত তথ্য প্রকাশ করে। এখানে ট্যাব ক্রমের সাথে ব্রাউজারটি পরবর্তী উপাদানটি পেতে ব্রাউজার কী করে তার একটি সরল প্রায় অনুমানকরণ:

var allowedTags = {input: true, textarea: true, button: true};

var walker = document.createTreeWalker(
  document.body,
  NodeFilter.SHOW_ELEMENT,
  {
    acceptNode: function(node)
    {
      if (node.localName in allowedTags)
        return NodeFilter.FILTER_ACCEPT;
      else
        NodeFilter.FILTER_SKIP;
    }
  },
  false
);
walker.currentNode = currentElement;
if (!walker.nextNode())
{
  // Restart search from the start of the document
  walker.currentNode = walker.root;
  walker.nextNode();
}
if (walker.currentNode && walker.currentNode != walker.root)
  walker.currentNode.focus();

এটি কেবল কিছু ট্যাগ বিবেচনা করে এবং tabindexগুণাবলী উপেক্ষা করে তবে আপনি কী অর্জন করার চেষ্টা করছেন তার উপর নির্ভর করে যথেষ্ট হতে পারে।


3

দেখে মনে হচ্ছে আপনি tabIndexকোনও উপাদানটির ফোকাসযোগ্য কিনা তা নির্ধারণের জন্য তার সম্পত্তিটি পরীক্ষা করতে পারেন । যে উপাদানটি ফোকাসযোগ্য নয় সেগুলির একটি tabindex"-1" থাকে।

তারপরে আপনাকে কেবল ট্যাব স্টপের নিয়মগুলি জানতে হবে:

  • tabIndex="1" সর্বোচ্চ priorty আছে।
  • tabIndex="2" পরবর্তী সর্বোচ্চ অগ্রাধিকার রয়েছে।
  • tabIndex="3" পরবর্তী, এবং আরও
  • tabIndex="0" (বা ডিফল্টরূপে ট্যাবলযোগ্য) এর সর্বনিম্ন অগ্রাধিকার রয়েছে।
  • tabIndex="-1" (বা ডিফল্টরূপে টেবলযোগ্য নয়) কোনও ট্যাব স্টপ হিসাবে কাজ করে না।
  • একই ট্যাবআইন্ডেক্সযুক্ত দুটি উপাদানগুলির জন্য, ডোমে প্রথম যেটি উপস্থিত হয় তার উচ্চতর অগ্রাধিকার থাকে।

খাঁটি জাভাস্ক্রিপ্ট ব্যবহার করে ক্রমানুসারে ট্যাব স্টপগুলির তালিকা কীভাবে তৈরি করবেন তার একটি উদাহরণ এখানে রয়েছে:

function getTabStops(o, a, el) {
    // Check if this element is a tab stop
    if (el.tabIndex > 0) {
        if (o[el.tabIndex]) {
            o[el.tabIndex].push(el);
        } else {
            o[el.tabIndex] = [el];
        }
    } else if (el.tabIndex === 0) {
        // Tab index "0" comes last so we accumulate it seperately
        a.push(el);
    }
    // Check if children are tab stops
    for (var i = 0, l = el.children.length; i < l; i++) {
        getTabStops(o, a, el.children[i]);
    }
}

var o = [],
    a = [],
    stops = [],
    active = document.activeElement;

getTabStops(o, a, document.body);

// Use simple loops for maximum browser support
for (var i = 0, l = o.length; i < l; i++) {
    if (o[i]) {
        for (var j = 0, m = o[i].length; j < m; j++) {
            stops.push(o[i][j]);
        }
    }
}
for (var i = 0, l = a.length; i < l; i++) {
    stops.push(a[i]);
}

আমরা প্রথমে ডোমকে হেঁটে, সমস্ত ট্যাবগুলি তাদের সূচক অনুসারে ক্রমানুসারে সংগ্রহ করি। আমরা তখন চূড়ান্ত তালিকা একত্রিত। লক্ষ্য করুন যে আমরা 1, 2, 3, ইত্যাদির tabIndex="0"আইটেমগুলির পরে তালিকার একেবারে শেষে আইটেমগুলি যুক্ত করিtabIndex

একটি সম্পূর্ণরূপে কাজ উদাহরণস্বরূপ, যেখানে আপনি "এন্টার" কী ব্যবহার করে প্রায় ট্যাব, এই চেক আউট করতে পারেন জন্য বেহালার


3

ট্যাববেল একটি ছোট জেএস প্যাকেজ যা আপনাকে ট্যাব ক্রমের সমস্ত ট্যাবযোগ্য উপাদানগুলির একটি তালিকা দেয় । সুতরাং আপনি সেই তালিকার মধ্যে আপনার উপাদানটি খুঁজে পেতে পারেন, তারপরে পরবর্তী তালিকাতে প্রবেশের দিকে মনোনিবেশ করুন।

অন্যান্য উত্তরে উল্লিখিত জটিল প্রান্তের কেসগুলি প্যাকেজটি সঠিকভাবে পরিচালনা করে (উদাহরণস্বরূপ, কোনও পূর্বপুরুষ হতে পারে না display: none)। এবং এটি jQuery উপর নির্ভর করে না!

এই লেখার (সংস্করণ 1.1.1) হিসাবে এটির সতর্কতা রয়েছে যে এটি আইই 8 সমর্থন করে না এবং ব্রাউজার বাগগুলি এটি contenteditableসঠিকভাবে পরিচালনা করতে বাধা দেয় ।


2
function focusNextElement(){
  var focusable = [].slice.call(document.querySelectorAll("a, button, input, select, textarea, [tabindex], [contenteditable]")).filter(function($e){
    if($e.disabled || ($e.getAttribute("tabindex") && parseInt($e.getAttribute("tabindex"))<0)) return false;
    return true;
  }).sort(function($a, $b){
    return (parseFloat($a.getAttribute("tabindex") || 99999) || 99999) - (parseFloat($b.getAttribute("tabindex") || 99999) || 99999);
  });
  var focusIndex = focusable.indexOf(document.activeElement);
  if(focusable[focusIndex+1]) focusable[focusIndex+1].focus();
};

1

এটি এসও তে আমার প্রথম পোস্ট, তাই গ্রহণযোগ্য উত্তরটি মন্তব্য করার মতো যথেষ্ট খ্যাতি আমার নেই, তবে আমাকে কোডটি নিম্নলিখিতটিতে সংশোধন করতে হয়েছিল:

export function focusNextElement () {
  //add all elements we want to include in our selection
  const focussableElements = 
    'a:not([disabled]), button:not([disabled]), input[type=text]:not([disabled])'
  if (document.activeElement && document.activeElement.form) {
      var focussable = Array.prototype.filter.call(
        document.activeElement.form.querySelectorAll(focussableElements),
      function (element) {
          // if element has tabindex = -1, it is not focussable
          if ( element.hasAttribute('tabindex') && element.tabIndex === -1 ){
            return false
          }
          //check for visibility while always include the current activeElement 
          return (element.offsetWidth > 0 || element.offsetHeight > 0 || 
            element === document.activeElement)
      });
      console.log(focussable)
      var index = focussable.indexOf(document.activeElement);
      if(index > -1) {
         var nextElement = focussable[index + 1] || focussable[0];
         console.log(nextElement)
         nextElement.focus()
      }                    
  }
}

ধীরে ধীরে ভার পরিবর্তন করা সমালোচনাযোগ্য নয়। মূল পরিবর্তনটি হ'ল আমরা সেই নির্বাচককে পরিত্রাণ পাই যা ট্যাবিনডেক্স পরীক্ষা করে! = "-1"। তারপরে, যদি উপাদানটিতে ট্যাবিনডেক্স বৈশিষ্ট্য থাকে এবং এটি "-1" তে সেট করা থাকে, আমরা এটি ফোকাসেবল বিবেচনা করি না।

আমার এটি পরিবর্তন করার প্রয়োজনীয় কারণটি হ'ল ট্যাবিনডেক্স = "- 1" টি যখন যুক্ত করার সময় <input>এই উপাদানটি তখনও মনোনিবেশযোগ্য বলে বিবেচিত হত কারণ এটি "ইনপুট [টাইপ = পাঠ্য]: নয় ([অক্ষম])" নির্বাচকের সাথে মেলে। আমার পরিবর্তনটি "যদি আমরা একটি অক্ষম অক্ষরযুক্ত পাঠ্য ইনপুট হয় এবং তার সাথে আমাদের একটি ট্যাব ইন্ডেক্স বৈশিষ্ট্য থাকে এবং সেই বৈশিষ্ট্যের মান -1 হয়, তবে আমাদের ফোকাসেবল হিসাবে বিবেচনা করা উচিত নয়।

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


1

নেই tabindex সম্পত্তি উপাদান সেট করা যাবে যে। এটি নির্দিষ্ট করে যে কোনওটি নির্বাচন করার সময় এবং ট্যাব টিপানোর সময় ইনপুট উপাদানগুলি পুনরায় করা উচিত order 0-র উপরে মানগুলি কাস্টম নেভিগেশনের জন্য সংরক্ষিত আছে, 0 "প্রাকৃতিক ক্রমে" (প্রথম উপাদানটির জন্য সেট করা থাকলে এটি আলাদাভাবে আচরণ করবে), -১ এর অর্থ কী-বোর্ডকে ফোকাসযোগ্য নয়:

<!-- navigate with tab key: -->
<input tabindex="1" type="text"/>
<input tabindex="2" type="text"/>

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

না, নেভিগেশনের এই কাস্টম পাথকে সমর্থন করার জন্য আপনার জিকুয়ারি বা কোনও স্ক্রিপ্টিংয়ের কোনও দরকার নেই। আপনি কোনও জাভাস্ক্রিপ্ট সমর্থন ছাড়াই এটি সার্ভার সাইডে প্রয়োগ করতে পারেন। অন্য দিক থেকে, সম্পত্তিটি প্রতিক্রিয়া কাঠামোর ক্ষেত্রেও সূক্ষ্মভাবে কাজ করে তবে এটির প্রয়োজন হয় না।


0

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

function focusNextElement( reverse, activeElem ) {
  /*check if an element is defined or use activeElement*/
  activeElem = activeElem instanceof HTMLElement ? activeElem : document.activeElement;

  let queryString = [
      'a:not([disabled]):not([tabindex="-1"])',
      'button:not([disabled]):not([tabindex="-1"])',
      'input:not([disabled]):not([tabindex="-1"])',
      'select:not([disabled]):not([tabindex="-1"])',
      '[tabindex]:not([disabled]):not([tabindex="-1"])'
      /* add custom queries here */
    ].join(','),
    queryResult = Array.prototype.filter.call(document.querySelectorAll(queryString), elem => {
      /*check for visibility while always include the current activeElement*/
      return elem.offsetWidth > 0 || elem.offsetHeight > 0 || elem === activeElem;
    }),
    indexedList = queryResult.slice().filter(elem => {
      /* filter out all indexes not greater than 0 */
      return elem.tabIndex == 0 || elem.tabIndex == -1 ? false : true;
    }).sort((a, b) => {
      /* sort the array by index from smallest to largest */
      return a.tabIndex != 0 && b.tabIndex != 0 
        ? (a.tabIndex < b.tabIndex ? -1 : b.tabIndex < a.tabIndex ? 1 : 0) 
        : a.tabIndex != 0 ? -1 : b.tabIndex != 0 ? 1 : 0;
    }),
    focusable = [].concat(indexedList, queryResult.filter(elem => {
      /* filter out all indexes above 0 */
      return elem.tabIndex == 0 || elem.tabIndex == -1 ? true : false;
    }));

  /* if reverse is true return the previous focusable element
     if reverse is false return the next focusable element */
  return reverse ? (focusable[focusable.indexOf(activeElem) - 1] || focusable[focusable.length - 1]) 
    : (focusable[focusable.indexOf(activeElem) + 1] || focusable[0]);
}

0

@ কানো এবং @ এমএক্স প্রস্তাবিত দুর্দান্ত সমাধানটিতে এটি একটি সম্ভাব্য বর্ধন । আপনি যদি ট্যাব ইন্ডেক্সের ক্রম সংরক্ষণ করতে চান তবে এই সাজটিকে মাঝখানে যুক্ত করুন:

// Sort by explicit Tab Index, if any
var sort_by_TabIndex = function (elementA, elementB) {
    let a = elementA.tabIndex || 1;
    let b = elementB.tabIndex || 1;
    if (a < b) { return -1; }
    if (a > b) { return 1; }
    return 0;
}
focussable.sort(sort_by_TabIndex);

0

আপনি এই কল করতে পারেন:

ট্যাব:

$.tabNext();

শিফট + ট্যাব:

$.tabPrev();

<!DOCTYPE html>
<html>
<body>
<script src="https://code.jquery.com/jquery-3.3.1.js" integrity="sha256-2Kok7MbOyxpgUVvAk/HJ2jigOSYS2auK4Pfzbm7uH60=" crossorigin="anonymous"></script>
<script>
(function($){
	'use strict';

	/**
	 * Focusses the next :focusable element. Elements with tabindex=-1 are focusable, but not tabable.
	 * Does not take into account that the taborder might be different as the :tabbable elements order
	 * (which happens when using tabindexes which are greater than 0).
	 */
	$.focusNext = function(){
		selectNextTabbableOrFocusable(':focusable');
	};

	/**
	 * Focusses the previous :focusable element. Elements with tabindex=-1 are focusable, but not tabable.
	 * Does not take into account that the taborder might be different as the :tabbable elements order
	 * (which happens when using tabindexes which are greater than 0).
	 */
	$.focusPrev = function(){
		selectPrevTabbableOrFocusable(':focusable');
	};

	/**
	 * Focusses the next :tabable element.
	 * Does not take into account that the taborder might be different as the :tabbable elements order
	 * (which happens when using tabindexes which are greater than 0).
	 */
	$.tabNext = function(){
		selectNextTabbableOrFocusable(':tabbable');
	};

	/**
	 * Focusses the previous :tabbable element
	 * Does not take into account that the taborder might be different as the :tabbable elements order
	 * (which happens when using tabindexes which are greater than 0).
	 */
	$.tabPrev = function(){
		selectPrevTabbableOrFocusable(':tabbable');
	};

    function tabIndexToInt(tabIndex){
        var tabIndexInded = parseInt(tabIndex);
        if(isNaN(tabIndexInded)){
            return 0;
        }else{
            return tabIndexInded;
        }
    }

    function getTabIndexList(elements){
        var list = [];
        for(var i=0; i<elements.length; i++){
            list.push(tabIndexToInt(elements.eq(i).attr("tabIndex")));
        }
        return list;
    }

    function selectNextTabbableOrFocusable(selector){
        var selectables = $(selector);
        var current = $(':focus');

        // Find same TabIndex of remainder element
        var currentIndex = selectables.index(current);
        var currentTabIndex = tabIndexToInt(current.attr("tabIndex"));
        for(var i=currentIndex+1; i<selectables.length; i++){
            if(tabIndexToInt(selectables.eq(i).attr("tabIndex")) === currentTabIndex){
                selectables.eq(i).focus();
                return;
            }
        }

        // Check is last TabIndex
        var tabIndexList = getTabIndexList(selectables).sort(function(a, b){return a-b});
        if(currentTabIndex === tabIndexList[tabIndexList.length-1]){
            currentTabIndex = -1;// Starting from 0
        }

        // Find next TabIndex of all element
        var nextTabIndex = tabIndexList.find(function(element){return currentTabIndex<element;});
        for(var i=0; i<selectables.length; i++){
            if(tabIndexToInt(selectables.eq(i).attr("tabIndex")) === nextTabIndex){
                selectables.eq(i).focus();
                return;
            }
        }
    }

	function selectPrevTabbableOrFocusable(selector){
		var selectables = $(selector);
		var current = $(':focus');

		// Find same TabIndex of remainder element
        var currentIndex = selectables.index(current);
        var currentTabIndex = tabIndexToInt(current.attr("tabIndex"));
        for(var i=currentIndex-1; 0<=i; i--){
            if(tabIndexToInt(selectables.eq(i).attr("tabIndex")) === currentTabIndex){
                selectables.eq(i).focus();
                return;
            }
        }

        // Check is last TabIndex
        var tabIndexList = getTabIndexList(selectables).sort(function(a, b){return b-a});
        if(currentTabIndex <= tabIndexList[tabIndexList.length-1]){
            currentTabIndex = tabIndexList[0]+1;// Starting from max
        }

        // Find prev TabIndex of all element
        var prevTabIndex = tabIndexList.find(function(element){return element<currentTabIndex;});
        for(var i=selectables.length-1; 0<=i; i--){
            if(tabIndexToInt(selectables.eq(i).attr("tabIndex")) === prevTabIndex){
                selectables.eq(i).focus();
                return;
            }
        }
	}

	/**
	 * :focusable and :tabbable, both taken from jQuery UI Core
	 */
	$.extend($.expr[ ':' ], {
		data: $.expr.createPseudo ?
			$.expr.createPseudo(function(dataName){
				return function(elem){
					return !!$.data(elem, dataName);
				};
			}) :
			// support: jQuery <1.8
			function(elem, i, match){
				return !!$.data(elem, match[ 3 ]);
			},

		focusable: function(element){
			return focusable(element, !isNaN($.attr(element, 'tabindex')));
		},

		tabbable: function(element){
			var tabIndex = $.attr(element, 'tabindex'),
				isTabIndexNaN = isNaN(tabIndex);
			return ( isTabIndexNaN || tabIndex >= 0 ) && focusable(element, !isTabIndexNaN);
		}
	});

	/**
	 * focussable function, taken from jQuery UI Core
	 * @param element
	 * @returns {*}
	 */
	function focusable(element){
		var map, mapName, img,
			nodeName = element.nodeName.toLowerCase(),
			isTabIndexNotNaN = !isNaN($.attr(element, 'tabindex'));
		if('area' === nodeName){
			map = element.parentNode;
			mapName = map.name;
			if(!element.href || !mapName || map.nodeName.toLowerCase() !== 'map'){
				return false;
			}
			img = $('img[usemap=#' + mapName + ']')[0];
			return !!img && visible(img);
		}
		return ( /^(input|select|textarea|button|object)$/.test(nodeName) ?
			!element.disabled :
			'a' === nodeName ?
				element.href || isTabIndexNotNaN :
				isTabIndexNotNaN) &&
			// the element and all of its ancestors must be visible
			visible(element);

		function visible(element){
			return $.expr.filters.visible(element) && !$(element).parents().addBack().filter(function(){
				return $.css(this, 'visibility') === 'hidden';
			}).length;
		}
	}
})(jQuery);
</script>

<a tabindex="5">5</a><br>
<a tabindex="20">20</a><br>
<a tabindex="3">3</a><br>
<a tabindex="7">7</a><br>
<a tabindex="20">20</a><br>
<a tabindex="0">0</a><br>

<script>
var timer;
function tab(){
    window.clearTimeout(timer)
    timer = window.setInterval(function(){$.tabNext();}, 1000);
}
function shiftTab(){
    window.clearTimeout(timer)
    timer = window.setInterval(function(){$.tabPrev();}, 1000);
}
</script>
<button tabindex="-1" onclick="tab()">Tab</button>
<button tabindex="-1" onclick="shiftTab()">Shift+Tab</button>

</body>
</html>

আমি jquery.tabbable প্লাগইন সম্পূর্ণ করতে পরিবর্তন ।


এই উত্তরটির সদৃশ , যা সেই jQuery প্লাগইনটির নির্মাতা পোস্ট করেছিলেন।
mbomb007

0

Necromancing।
আমার কাছে 0-ট্যাবআইডেক্সের একটি গুচ্ছ রয়েছে, যা আমি কীবোর্ডের সাহায্যে নেভিগেট করতে চেয়েছিলাম।
যেহেতু, কেবলমাত্র উপাদানগুলির অর্ডার ম্যাটার করে, আমি এটি ব্যবহার করে করেছিdocument.createTreeWalker

সুতরাং প্রথমে আপনি ফিল্টারটি তৈরি করুন (আপনি কেবল [দৃশ্যমান] উপাদানগুলি চান, যার একটি NUMERICAL মান সহ "ট্যাব ইন্ডেক্স" বৈশিষ্ট্য রয়েছে।

তারপরে আপনি রুট নোড সেট করেছেন, এর বাইরে আপনি অনুসন্ধান করতে চান না। আমার ক্ষেত্রে, this.m_treeএকটি আল-উপাদানটি রয়েছে যা একটি টোগেবল গাছ রয়েছে। পরিবর্তে যদি আপনি পুরো দস্তাবেজটি চান তবে কেবল এটির this.m_treeসাথে প্রতিস্থাপন করুন document.documentElement

তারপরে আপনি বর্তমান নোডটিকে বর্তমান সক্রিয় উপাদানটিতে সেট করেছেন:

ni.currentNode = el; // el = document.activeElement

তারপর আপনি ফিরে ni.nextNode()বা ni.previousNode()

দ্রষ্টব্য:
যদি আপনার ট্যাবইন্ডিস থাকে তবে এটি সঠিক ক্রমে ট্যাবগুলি ফিরিয়ে দেবে না! = 0 এবং উপাদান ক্রমটি ট্যাবআইন্ডেক্স ক্রম নয়। ট্যাবআইন্ডেক্স = 0 এর ক্ষেত্রে, ট্যাবর্ডারটি সর্বদা উপাদান ক্রম হয়, এই কারণেই এটি কাজ করে (সেই ক্ষেত্রে)।

protected createFilter(fn?: (node: Node) => number): NodeFilter
{
    // Accept all currently filtered elements.
    function acceptNode(node: Node): number 
    {
        return NodeFilter.FILTER_ACCEPT;
    }

    if (fn == null)
        fn = acceptNode;


    // Work around Internet Explorer wanting a function instead of an object.
    // IE also *requires* this argument where other browsers don't.
    const safeFilter: NodeFilter = <NodeFilter><any>fn;
    (<any>safeFilter).acceptNode = fn;

    return safeFilter;
}



protected createTabbingFilter(): NodeFilter
{
    // Accept all currently filtered elements.
    function acceptNode(node: Node): number 
    {
        if (!node)
            return NodeFilter.FILTER_REJECT;

        if (node.nodeType !== Node.ELEMENT_NODE)
            return NodeFilter.FILTER_REJECT;

        if (window.getComputedStyle(<Element>node).display === "none")
            return NodeFilter.FILTER_REJECT;

        // "tabIndex": "0"
        if (!(<Element>node).hasAttribute("tabIndex"))
            return NodeFilter.FILTER_SKIP;

        let tabIndex = parseInt((<Element>node).getAttribute("tabIndex"), 10);
        if (!tabIndex || isNaN(tabIndex) || !isFinite(tabIndex))
            return NodeFilter.FILTER_SKIP;

        // if ((<Element>node).tagName !== "LI") return NodeFilter.FILTER_SKIP;

        return NodeFilter.FILTER_ACCEPT;
    }

    return this.createFilter(acceptNode);
}


protected getNextTab(el: HTMLElement): HTMLElement
{
    let currentNode: Node;
    // https://developer.mozilla.org/en-US/docs/Web/API/Document/createNodeIterator
    // https://developer.mozilla.org/en-US/docs/Web/API/Document/createTreeWalker

    // let ni = document.createNodeIterator(el, NodeFilter.SHOW_ELEMENT);
    // let ni = document.createTreeWalker(this.m_tree, NodeFilter.SHOW_ELEMENT);
    let ni = document.createTreeWalker(this.m_tree, NodeFilter.SHOW_ELEMENT, this.createTabbingFilter(), false);

    ni.currentNode = el;

    while (currentNode = ni.nextNode())
    {
        return <HTMLElement>currentNode;
    }

    return el;
}


protected getPreviousTab(el: HTMLElement): HTMLElement
{
    let currentNode: Node;
    let ni = document.createTreeWalker(this.m_tree, NodeFilter.SHOW_ELEMENT, this.createTabbingFilter(), false);
    ni.currentNode = el;

    while (currentNode = ni.previousNode())
    {
        return <HTMLElement>currentNode;
    }

    return el;
}

নোট করুন যে সময় লুপ

while (currentNode = ni.nextNode())
{
    // Additional checks here
    // if(condition) return currentNode;
    // else the loop continues;
    return <HTMLElement>currentNode; // everything is already filtered down to what we need here
}

কেবলমাত্র যদি সেখানে আপনি চান তবেই আপনার অতিরিক্ত মানদণ্ড থাকে যা আপনি ক্রিয়েটরিওয়ালকারকে দেওয়া ফিল্টারে ফিল্টার করতে পারবেন না।

উল্লেখ্য এই টাইপ করা বিষয় হয়, তাহলে আপনি কোলন (:) পিছনে সব টোকেন মুছে ফেলার জন্য প্রয়োজন, কোণ-বন্ধনীর মধ্যে (<>), যেমন <Element>বা :(node: Node) => numberবৈধ জাভাস্ক্রিপ্ট জন্য।

এখানে পরিষেবা হিসাবে, পরিবহিত জেএস:

"use strict";
function createFilter(fn) {
    // Accept all currently filtered elements.
    function acceptNode(node) {
        return NodeFilter.FILTER_ACCEPT;
    }
    if (fn == null)
        fn = acceptNode;
    // Work around Internet Explorer wanting a function instead of an object.
    // IE also *requires* this argument where other browsers don't.
    const safeFilter = fn;
    safeFilter.acceptNode = fn;
    return safeFilter;
}
function createTabbingFilter() {
    // Accept all currently filtered elements.
    function acceptNode(node) {
        if (!node)
            return NodeFilter.FILTER_REJECT;
        if (node.nodeType !== Node.ELEMENT_NODE)
            return NodeFilter.FILTER_REJECT;
        if (window.getComputedStyle(node).display === "none")
            return NodeFilter.FILTER_REJECT;
        // "tabIndex": "0"
        if (!node.hasAttribute("tabIndex"))
            return NodeFilter.FILTER_SKIP;
        let tabIndex = parseInt(node.getAttribute("tabIndex"), 10);
        if (!tabIndex || isNaN(tabIndex) || !isFinite(tabIndex))
            return NodeFilter.FILTER_SKIP;
        // if ((<Element>node).tagName !== "LI") return NodeFilter.FILTER_SKIP;
        return NodeFilter.FILTER_ACCEPT;
    }
    return createFilter(acceptNode);
}
function getNextTab(el) {
    let currentNode;
    // https://developer.mozilla.org/en-US/docs/Web/API/Document/createNodeIterator
    // https://developer.mozilla.org/en-US/docs/Web/API/Document/createTreeWalker
    // let ni = document.createNodeIterator(el, NodeFilter.SHOW_ELEMENT);
    // let ni = document.createTreeWalker(this.m_tree, NodeFilter.SHOW_ELEMENT);
    let ni = document.createTreeWalker(document.documentElement, NodeFilter.SHOW_ELEMENT, createTabbingFilter(), false);
    ni.currentNode = el;
    while (currentNode = ni.nextNode()) {
        return currentNode;
    }
    return el;
}
function getPreviousTab(el) {
    let currentNode;
    let ni = document.createTreeWalker(document.documentElement, NodeFilter.SHOW_ELEMENT, createTabbingFilter(), false);
    ni.currentNode = el;
    while (currentNode = ni.previousNode()) {
        return currentNode;
    }
    return el;
}

0

আমি এই কোড ব্যবহার

    $(document).on('change', 'select', function () {
    let next_select = $(this);
// console.log(next_select.toArray())
    if (!next_select.parent().parent().next().find('select').length) {
        next_select.parent().parent().parent().next().find('input[type="text"]').click()
        console.log(next_select.parent().parent().parent().next());
    } else if (next_select.parent().parent().next().find('select').prop("disabled")) {
        setTimeout(function () {
            next_select.parent().parent().next().find('select').select2('open')
        }, 1000)
        console.log('b');
    } else if (next_select.parent().parent().next().find('select').length) {
        next_select.parent().parent().next().find('select').select2('open')
        console.log('c');
    }
});

হাই, আপনি যদি কোডটি কিছুটা ব্যাখ্যা করেন তবে দুর্দান্ত হবে, এটি নতুন পাঠকদের আরও ভালভাবে বুঝতে সাহায্য করবে। ধন্যবাদ
সুনীল লুলা

0

এই জাতীয় ট্যাব নেভিগেশন কৌশলগুলির জন্য এই খাঁটি জেএস এনপিএম গ্রন্থাগারটি উল্লেখ করুন।
কীবোর্ড-নেভিগেটর
এই ছোট লাইব্রেরিটি ট্যাব কী, তীর কী নেভিগেশন, ডোম আপডেটগুলিতে ফোকাস ধরে রাখা, মডেল ফোকাস ট্র্যাপ, ফালব্যাক ফোকাস পরিচালনা করে।


0

পরামর্শের একটি শব্দ: কোনও ট্যাব ইভেন্টের সময় ফোকাস কোথায় আসে তা নিয়ন্ত্রণ করার চেষ্টা করবেন না । পরিবর্তে নিয়ন্ত্রণ করতে যা উপাদান এবং সেটিং দ্বারা tabbable নয় চেষ্টা tabIndexউপাদান তোমাদের না ফোকাস পেতে চাই -1। যেমন

// `tabContainer` is a container where we want only
// element at a time to be tabbable, e.g. a radio menu.

tabContainer.addEventListener("focusin", () => {
  const desired = findDesiredFocusElement();

  if (!desired) {
    // Just leave the focus be. We have no preference
    // at the moment.
    return;
  }

  // Move the focus to the correct element.
  desired.focus();

  // Remove all undesired elements from the tab order.
  for (const undesired of findUndesiredFocusElements()) {
    // Make it untabbable.
    undesired.tabIndex = -1;
  }
});

tabContainer.addEventListener("focusout", (event) => {
  for (const element of findRelevantFocusElements()) {
    // Give each element back their focus capability.
    element.tabIndex = 0;
  }
});

নোট: এই নাও হতে কি আপনার অবস্থা, যেমন আপনার ক্ষেত্রে সেরা কি এটা ভাল কিছু ট্যাব সূচি নিয়ন্ত্রণ করতে হতে পারে changeইভেন্ট বা না রিসেট করতে tabIndexরাজ্যের focusoutইত্যাদি

আরও তথ্য এখানে


-1

আপনি যে প্রতিটি উপাদানটি দিয়ে চক করতে চান তার জন্য আপনি কি নিজের ট্যাব ইন্ডেক্স মানগুলি নির্দিষ্ট করেছেন? যদি তা হয় তবে আপনি এটি চেষ্টা করতে পারেন:

var lasTabIndex = 10; //Set this to the highest tabIndex you have
function OnFocusOut()
{
    var currentElement = $get(currentElementId); // ID set by OnFocusIn 

    var curIndex = $(currentElement).attr('tabindex'); //get the tab index of the current element
    if(curIndex == lastTabIndex) { //if we are on the last tabindex, go back to the beginning
        curIndex = 0;
    }
    $('[tabindex=' + (curIndex + 1) + ']').focus(); //set focus on the element that has a tab index one greater than the current tab index
}

আপনি jquery ব্যবহার করছেন, তাই না?


অ্যাপ্লিকেশনটি ভেঙে যাওয়ার কারণে আমরা জিকুয়ারি ব্যবহার করছি না। : /
জাদজিয়ার এমডি

ঠিক আছে, আমি মনে করি আমি পুনর্লিখন করতে পারি jquery ব্যবহার না করেই, আমাকে একটি মিনিট দিন
ব্রায়ান গ্লাজ

আমরা আগ্রহী প্রতিটি উপাদানগুলির ট্যাব সূচক মান সেট করা থাকে।
জাদজিয়ার এমডি

-1

আমি উপরের সমাধানগুলি চেক করেছি এবং সেগুলি বেশ লম্বা পেয়েছি। এটি কোডের এক লাইন দিয়েই সম্পন্ন করা যায়:

currentElement.nextElementSibling.focus();

বা

currentElement.previousElementSibling.focus();

এখানে বর্তমান উপাদানটি কোনও ie ডকুমেন্ট.একটিভ এলিমেন্ট বা এটি হতে পারে যদি বর্তমান উপাদানটি ফাংশনের প্রসঙ্গে থাকে।

আমি কীডাউন ইভেন্ট সহ ট্যাব এবং শিফট-ট্যাব ইভেন্টগুলি ট্র্যাক করেছি

let cursorDirection = ''
$(document).keydown(function (e) {
    let key = e.which || e.keyCode;
    if (e.shiftKey) {
        //does not matter if user has pressed tab key or not.
        //If it matters for you then compare it with 9
        cursorDirection = 'prev';
    }
    else if (key == 9) {
        //if tab key is pressed then move next.
        cursorDirection = 'next';
    }
    else {
        cursorDirection == '';
    }
});

একবার আপনার কার্সার দিকনির্দেশ পরে আপনি ব্যবহার করতে পারেন nextElementSibling.focusবা previousElementSibling.focusপদ্ধতিগুলি


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