2016-08-17 46 views
1

這裏緊跟我的模型:找到相應的DOM元素

<!-- 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 --> 

和我的視圖模型:

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); 

對於每個成員,我們有(爲七天一週的每一天)一輪班次數。對於每個班次,我們都有一對startTime-endTime輸入。 就視覺效果而言,有一排包括一名成員的每週輪班,可能是每名成員每天有多班輪換。如果我們看一下欄目,這些欄目包括所有成員在某一天的所有輪班。
我最大的問題是,我希望每當endTime的DOM元素上有一個blur事件時,就會集中在垂直方向上的startTime 的DOM元素。例如,如果我們在星期一,並且第一個成員有兩個班次,那麼我想關注發生模糊的第一個成員的第二班次的startTime到第一班班的結束時間,然後是第一班班的startTime在第二個成員的星期一當模糊發生到第一個成員的第二個輪班的結束時間時。週二也是如此。我該如何實現這一目標?目前,光標正在水平移動。

+0

對於你要在它們之間跳轉什麼事件?按Tab鍵?! –

+0

模糊事件endTime –

+0

爲什麼不在輸入中使用'tabindex'? –

回答

1

這應該爲你工作...

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(); 
    } 
    }); 
}); 

的想法是綁定的事件處理程序模糊包含value: endTimedata-bind屬性每個輸入的事件。
如果這個處理程序中,我們發現在一天endTime輸入的索引,把它加1,並與(日)

該指數在同一個TD集中startTime輸入由於要素不存在的權力後的文件被加載(但是由knockout渲染),我們將處理程序綁定到body,以獲取由input[data-bind*='value: endTime']選擇的輸入。

+0

非常感謝。你應該得到100分。不過,如果你澄清兩件事情,我會更高興。首先,我們爲什麼必須編寫'data-bind *'而不是'data-bind'?第二個是如果我嘗試'$ td.css(「backgroundColor」,「red」)'不起作用。爲什麼以及如何讓它工作? –

+1

即使我喜歡這個答案的簡單性,我覺得我應該評論說,混合jQuery和像這樣的挖空是不好的習慣,並且最終會讓你陷入困境。一般規則是:如果在使用knockout時需要對DOM做任何事情,請通過_custom binding_來完成。 – user3297291

+0

@ILIAS,我們可以在沒有明星的情況下編寫'[data-bind =「value:endTime」]',它會查找'data-bind'正好等於'value:endTime'的元素,其中'* = '會查找'data-bind'包含'value:endTime'的元素...... – shramee

2

在這裏,我通過使用所有knockout向您展示其中的一種方法。這表明你的邏輯如何實現你的,因爲我沒有你的數據樣本,您可能需要根據您的數據

工作實例進行修改:https://jsfiddle.net/kyr6w2x3/48/

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:

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()); 
+0

很好的努力,但它不是我正在尋找的人。我寧願不使用新的屬性(id)並根據現有的視圖模型找到解決方案。 –

1

我的建議是使用計算的tabindex屬性。

  • 在你$root視圖模型,就像你希望他們能夠在對焦方面,我們將計算的有序shift.startend觀測陣列。
  • 我們還將製作一個工廠方法,該方法返回每個<input>綁定的計算索引。
  • 每個輸入得到一個attr: { 'tabindex': getTabIndex() }綁定確保該指數保持最新

這種方法將適用於使用標籤鍵通過表單導航人的工作。最重要的是;現在您已經有了排序後的輸入觀察值的計算列表,您可以輕鬆地綁定到事件以選擇上一個/下一個。

下面是一個例子:

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>