简体   繁体   English

找到适当的DOM元素

[英]Find the appropriate DOM element

Here follows my model: 这是我的模型:

<!-- ko foreach: teamMembers -->
    <tr>
      <!-- ko foreach: days -->   
      <td>
        <!-- ko foreach: shifts -->
          <input type="text" data-bind="value: startTime">
          <input type="text" data-bind="value: endTime">          
       <!-- /ko -->
      </td>
      <!-- /ko -->       
    </tr>
<!-- /ko -->

and my viewmodel: 和我的视图模型:

function TimeCardViewModel() {
    var self = this;
    self.teamMembers=ko.observableArray();
  }

function TeamMemberViewModel(data){
    var self=this;
    self.days=ko.observableArray();
    for (var i=0; i<7; i++)  {
      self.days.push(new DayViewModel(...);
    }
  }

function DayViewModel(shifts){
    var self=this;
    self.shifts=ko.observableArray();
    for (var i=0; i<shifts.length; i++)  {
       self.shifts.push(new ShiftElementsViewModel(...);
    } 
  }

function ShiftElementsViewModel(a,b,c,d) {
    var self=this;
    self.startTime=ko.observable(a);
    self.endTime=ko.observable(b);
  }

var timeCardViewModel=new TimeCardViewModel();
ko.applyBindings(timeCardViewModel);

For each member, we have (for each day of the seven days of the week) a number of shifts. 对于每个成员,我们(对于一周中的7天的每一天)都有许多班次。 For each shift, we have pairs of startTime-endTime inputs. 对于每个班次,我们都有成对的startTime-endTime输入。 As far as the visual result is concerned, there are rows which include all the weekly shifts of a member and it might be the case of multiple shifts per day per member. 就可视化结果而言,有些行包含一个成员的所有每周轮班,并且可能是每个成员每天多次轮班的情况。 If we look at the columns, these include all the shifts for all the members for a certain day. 如果我们查看这些列,则这些列包括某天所有成员的所有班次。
My great problem is that I want, whenever there is a blur event on the DOM element of endTime, to focus on the DOM element of startTime vertically . 我的大问题是,我希望每当endTime的DOM元素上发生blur事件时,都垂直关注startTime的DOM元素。 For example, if we are on Monday and the first member has two shifts I want to focus on the startTime of the second shift of the first member when blur is occurring to the endTime of the first shift and then on the startTime of the first shift on Monday of the second member when blur is occurring to the endTime of the second shift of the first member. 例如,如果我们在星期一,并且第一个成员有两个班次,那么我想集中在发生模糊时第一个成员的第二个班次的startTime到第一个班次的endTime上,然后关注第一个班次的startTime发生模糊时,第二个成员的星期一到第一个成员的第二个班次的结束时间。 The same for Tuesday etc. How may I achieve that? 星期二等也一样。如何实现? For the time being, the cursor is travelling horizontally. 暂时,光标在水平移动。

Here i am showing you one of the approaches by using all knockout . 在这里,我向您展示使用所有knockout的方法之一。 It shows you the logic how to implement yours since I don't have your data sample and you might need to modify it based on your data 它向您展示了如何实现您的逻辑,因为我没有您的数据示例,您可能需要根据数据进行修改

Working example : https://jsfiddle.net/kyr6w2x3/48/ 工作示例https : //jsfiddle.net/kyr6w2x3/48/

HTML: HTML:

<table>
 <tbody>
   <!-- ko foreach: teamMembers -->
    <tr>
    <td data-bind="text:name"></td>
      <!-- ko foreach: days -->   
      <td>
      <h4 data-bind="text:name"></h4>
          <input type="text" data-bind="value: startTime ,hasFocus :getFocus">
          <input type="text" data-bind="value: endTime ,event:{blur: $root.endTimeBlur}">          

      </td>
      <!-- /ko -->       
    </tr>
<!-- /ko -->
 </tbody>
</table>

JS: JS:

var data ={
    teamMembers: [{
        Name: "Member A",
    id:1,
        days: [{startTime: '8:00',endTime: "4:00" ,name:'Monday',parentId:1},{startTime: '8:00',endTime: "4:00",name:'Tuesday',parentId:1},{startTime: '8:00',endTime: "4:00",name:'Wednesday',parentId:1},{startTime: '8:00',endTime: "4:00",name:'Thursday',parentId:1},{startTime: '8:00',endTime: "4:00",name:'Friday',parentId:1},{startTime: '8:00',endTime: "4:00",name:'Saturday',parentId:1},{startTime: '8:00',endTime: "4:00",name:'Sunday',parentId:1}]
    },
                   {
        Name: "Member B",
    id:2,
        days: [{startTime: '8:00',endTime: "4:00" ,name:'Monday' ,parentId:2},{startTime: '8:00',endTime: "4:00",name:'Tuesday' ,parentId:2},{startTime: '8:00',endTime: "4:00",name:'Wednesday',parentId:2},{startTime: '8:00',endTime: "4:00",name:'Thursday',parentId:2},{startTime: '8:00',endTime: "4:00",name:'Friday',parentId:2},{startTime: '8:00',endTime: "4:00",name:'Saturday',parentId:2},{startTime: '8:00',endTime: "4:00",name:'Sunday',parentId:2}]
    },
  {
        Name: "Member C",
    id:3,
        days: [{startTime: '8:00',endTime: "4:00" ,name:'Monday',parentId:3},{startTime: '8:00',endTime: "4:00",name:'Tuesday',parentId:3},{startTime: '8:00',endTime: "4:00",name:'Wednesday',parentId:3},{startTime: '8:00',endTime: "4:00",name:'Thursday',parentId:3},{startTime: '8:00',endTime: "4:00",name:'Friday',parentId:3},{startTime: '8:00',endTime: "4:00",name:'Saturday',parentId:3},{startTime: '8:00',endTime: "4:00",name:'Sunday',parentId:3}]
    },]

}
var memberViewModel = function(data) {
 var self = this ;
 self.days = ko.observableArray([]);
 self.name = ko.observable(data.Name);
 self.id = ko.observable(data.id); 
 self.days($.map(data.days, function (item) {
    return new daysViewModel(item);
 }));

}
var daysViewModel = function (data){
 var self = this ;
 self.getFocus = ko.observable(false);
 self.startTime = ko.observable(data.startTime);
 self.endTime = ko.observable(data.endTime);
 self.name = ko.observable(data.name)
 self.parentId = ko.observable(data.parentId);
}

function ViewModel() {
  var self = this;
  self.teamMembers = ko.observableArray([]);
  self.teamMembers($.map(data.teamMembers, function (item) {
    return new memberViewModel(item);
  }));
  self.endTimeBlur = function(data){
    ko.utils.arrayFirst(self.teamMembers(), function (item,i) {
      if (item.id() == data.parentId() && self.teamMembers()[i+1] ) {
        //here you set getFocus to true to make next member 's monday gets focus    
        self.teamMembers()[i+1].days()[0].getFocus(true);
        return;
      }
    });
  }
}  
  ko.applyBindings(new ViewModel());

This should work for you... 这应该为您工作...

jQuery(function($) {
  $('body').on("blur", "input[data-bind*='value: endTime']", function() {
    var
      $t = $(this), // Current input
      $td = $t.closest('td'), // Current input's parent td
      i = $td.find('input[data-bind*="value: endTime"]').index($t), // Index of current input = current shift index
      $target = $td.find('input[data-bind*="value: startTime"]').eq(i + 1); // Target is current shift + 1

    if ($target.length) {
      $target.focus();
    }
  });
});

The idea is to bind an event handler to blur event of every input that contains value: endTime in data-bind attribute. 这个想法是绑定一个事件处理程序来模糊每个包含value: endTime事件value: endTime data-bind属性中的value: endTime
If this handler, we find out the index of endTime input in day, add 1 to it and focus the startTime input with that index in the same td (day) 😉 如果使用此处理程序,我们找出以天为单位的endTime输入的索引,将其加1,然后将startTime输入与该索引集中在同一td(天)中😉

Since the elements dont exist right after document is loaded (but rendered by knockout), we bind the handler to body for inputs selected by input[data-bind*='value: endTime'] . 由于元素在文档加载后不存在(而是通过剔除呈现),因此对于通过input[data-bind*='value: endTime']选择的input[data-bind*='value: endTime'] ,我们将处理程序绑定到主体。

My advice would be to use a computed tabindex attribute. 我的建议是使用计算出的tabindex属性。

  • In your $root viewmodel, we'll compute an array of shift.start and end observables ordered like you want them to be in terms of focus. 在您的$root视图模型中,我们将计算一个shift.startend可观察对象数组, shift.start排列方式就像您希望它们在焦点方面一样。
  • We'll also make a factory method that returns a computed index for each <input> bind. 我们还将创建一个工厂方法,该方法为每个<input>绑定返回一个计算索引。
  • Each input gets an attr: { 'tabindex': getTabIndex() } binding that makes sure the index stays up to date 每个输入都具有一个attr: { 'tabindex': getTabIndex() }绑定,以确保索引保持最新

This approach will work for people that use the tab key to navigate through the form. 此方法适用于使用Tab键浏览表单的人员。 Most importantly; 最重要的是; now that you have a computed list of sorted input observables, you can easily bind to events to select a previous/next one. 现在您已经有了一个计算后的可观察输入列表,您可以轻松地绑定到事件以选择上一个/下一个。

Here's an example: 这是一个例子:

 var Root = function() { this.members = ko.observableArray([]); for (var i = 0; i < 5; i += 1) { this.members.push(new Member()); } // Note: you could do this in less lines of code, but I wanted // to be extra transparent to show the structure of the data // transform. var orderedShiftInputs = ko.pureComputed(function() { // We want the days to be leading, so we create a // two-dimensional array: [[meber1day1, member2day1], [member1day2], etc] // Note: members _cannot_ skip days var mergedDays = []; this.members().forEach(function(member) { member.days().forEach(function(day, index) { if (!mergedDays[index]) { mergedDays[index] = []; } mergedDays[index] = mergedDays[index].concat(day); }); }); // We flatten the 2d-array of days to a list of shifts: // [member1day1shift1, member1day1shift2, member2day1shift1, etc] var mergedShifts = mergedDays.reduce(function(shifts, days) { var allShifts = days.reduce(function(all, day) { return all.concat(day.shifts()); }, []); return shifts.concat(allShifts); }, []); // We flatten the shifts into an array of start and end observables: // [member1day1shift1start, member1day1shift1end, etc.] return mergedShifts.reduce(function(inputs, shift) { return inputs.concat([shift.start, shift.end]); }, []); }, this); this.getTabIndex = function(data) { return ko.computed(function() { // Find the start or end data in our sorted array. // In this example, we can start with index 1. In your app, // there might be other input elements before the shifts... var START_TAB_INDEX = 1; return orderedShiftInputs().indexOf(data) + START_TAB_INDEX; }, this); }.bind(this); } var Member = function() { this.days = ko.observableArray([]); for (var i = 0; i < 2; i += 1) { this.days.push(new Day()); } } var Day = function() { this.shifts = ko.observableArray([]); for (var i = 0; i < 3; i += 1) { this.shifts.push(new Shift()); } } var Shift = function() { this.start = ko.observable(1); this.end = ko.observable(2); } ko.applyBindings(new Root()); 
 td { border: 1px solid black } input { display: inline; width: 30px; } 
 <script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script> <table> <tbody> <!-- ko foreach: members --> <tr> <td data-bind="text: 'Member-' + $index()"></td> <!-- ko foreach: days --> <td> <span data-bind="text: 'Day ' + $index()"></span> <br/> <!-- ko foreach: shifts --> <input type="text" data-bind="value: start, attr: { 'tabindex': $root.getTabIndex(start) }"> <input type="text" data-bind="value: end, attr: { 'tabindex': $root.getTabIndex(end) }"> <!-- /ko --> </td> <!-- /ko --> </tr> <!-- /ko --> </tbody> </table> 

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM