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. For each shift, we have pairs of startTime-endTime inputs.
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. 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. The same for Tuesday etc. How may I achieve that? For the time being, the cursor is travelling horizontally.
This should work for you...
The idea is to bind an event handler to blur event of every input that contains
value: endTime
indata-bind
attribute.If this handler, we find out the index of
endTime
input in day, add 1 to it and focus thestartTime
input with that index in the same td (day)My advice would be to use a computed
tabindex
attribute.$root
viewmodel, we'll compute an array ofshift.start
andend
observables ordered like you want them to be in terms of focus.<input>
bind.attr: { 'tabindex': getTabIndex() }
binding that makes sure the index stays up to dateThis approach will work for people that use the tab key to navigate through the form. 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:
Here i am showing you one of the approaches by using all
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 dataWorking example : https://jsfiddle.net/kyr6w2x3/48/
HTML:
JS: