uki 1.0.0 → 1.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,10 +1,84 @@
1
+ uki.more.view.splitTable = {};
1
2
 
2
-
3
- uki.view.declare('uki.more.view.SplitTable', uki.view.Table, function(base) {
4
- var Rect = uki.geometry.Rect;
3
+ uki.view.declare('uki.more.view.SplitTable', uki.view.Container, function(Base) {
4
+ var Rect = uki.geometry.Rect,
5
+ Size = uki.geometry.Size;
6
+
7
+ var propertiesToDelegate = 'rowHeight data packSize visibleRectExt render selectedIndex focusable textSelectable multiselect'.split(' ');
5
8
 
6
9
 
7
10
  this._defaultHandlePosition = 200;
11
+ this._headerHeight = 17;
12
+
13
+ this._style = function(name, value) {
14
+ this._leftHeader.style(name, value);
15
+ this._rightHeader.style(name, value);
16
+ return Base._style.call(this, name, value);
17
+ };
18
+
19
+ this.columns = uki.newProp('_columns', function(c) {
20
+ this._columns = uki.build(c);
21
+ this._totalWidth = 0;
22
+ this._leftHeader.columns([this._columns[0]]);
23
+
24
+ this._columns[0].bind('beforeResize', uki.proxy(this._syncHandlePosition, this, this._columns[0]));
25
+
26
+ for (var i = 1; i < this._columns.length; i++) {
27
+ this._columns[i].position(i - 1);
28
+ this._columns[i].bind('beforeResize', uki.proxy(this._rightColumnResized, this, this._columns[i]));
29
+ };
30
+ this._updateTotalWidth();
31
+ this._rightHeader.columns(Array.prototype.slice.call(this._columns, 1));
32
+ this._splitPane.leftMin(this._columns[0].minWidth() - 1)
33
+ // this._splitPane.handlePosition(this._columns[0].width());
34
+ this._syncHandlePosition(this._splitPane);
35
+ });
36
+
37
+ uki.each(propertiesToDelegate, function(i, name) {
38
+ this[name] = function(v) {
39
+ if (v === undefined) return this._leftList[name]();
40
+ this._leftList[name](v);
41
+ this._rightList[name](v);
42
+ return this;
43
+ };
44
+ }, this);
45
+
46
+ this.hasFocus = function() {
47
+ return this._leftList.hasFocus() || this._rightList.hasFocus();
48
+ };
49
+
50
+ this.rightColumns = function() {
51
+ return this._rightHeader.columns();
52
+ };
53
+
54
+ this._rightColumnResized = function(column) {
55
+ this._updateTotalWidth();
56
+ this._horizontalScroll.layout();
57
+ };
58
+
59
+ this.rowHeight = function(value) {
60
+ if (value === undefined) return this._leftList.rowHeight();
61
+ this._leftList.rowHeight(value);
62
+ this._rightList.rowHeight(value);
63
+ return this;
64
+ };
65
+
66
+ this.data = function(d) {
67
+ if (d === undefined) return uki.map(this._leftList.data(), function(value, i) {
68
+ return [value].concat(this._rightList.data()[i]);
69
+ }, this);
70
+
71
+ this._leftList.data(uki.map(d, function(value) {
72
+ return [value[0]];
73
+ }));
74
+
75
+ this._rightList.data(uki.map(d, function(value) {
76
+ return value.slice(1);
77
+ }));
78
+
79
+ this._splitPane.minSize(new Size(0, this._leftList.minSize().height));
80
+ this._verticalScroll.layout();
81
+ };
8
82
 
9
83
  this._createDom = function() {
10
84
  Base._createDom.call(this);
@@ -14,20 +88,34 @@ uki.view.declare('uki.more.view.SplitTable', uki.view.Table, function(base) {
14
88
  [
15
89
  {
16
90
  view: 'table.Header',
17
- rect: new Rect(0, 0, this.rect().width, this._headerHeight),
18
- anchors: 'top left right',
19
- className: 'table-header'
91
+ rect: new Rect(this._defaultHandlePosition, this._headerHeight),
92
+ anchors: 'left top'
93
+ },
94
+ {
95
+ view: 'Box',
96
+ className: 'table-header-container',
97
+ style: { overflow: 'hidden' },
98
+ rect: new Rect(this._defaultHandlePosition, 0, this.rect().width - this._defaultHandlePosition - 1, this._headerHeight),
99
+ anchors: 'left top right',
100
+ childViews: {
101
+ view: 'table.Header',
102
+ rect: new Rect(this.rect().width - this._defaultHandlePosition - 1, this._headerHeight),
103
+ anchors: 'top left right',
104
+ className: 'table-header'
105
+ }
20
106
  },
21
107
  {
22
108
  view: 'ScrollPane',
23
109
  rect: new Rect(0, this._headerHeight, this.rect().width, bodyHeight),
24
110
  anchors: 'left top right bottom',
25
111
  className: 'table-v-scroll',
112
+ scrollV: true,
26
113
  childViews: [
27
114
  {
28
- view: 'SplitPane',
115
+ view: 'HSplitPane',
29
116
  rect: new Rect(this.rect().width, bodyHeight),
30
- anchors: 'left top',
117
+ anchors: 'left top right bottom',
118
+ className: 'table-horizontal-split-pane',
31
119
  handlePosition: this._defaultHandlePosition,
32
120
  handleWidth: 1,
33
121
  leftChildViews: [
@@ -40,19 +128,27 @@ uki.view.declare('uki.more.view.SplitTable', uki.view.Table, function(base) {
40
128
  ],
41
129
  rightChildViews: [
42
130
  {
43
- view: 'ScrollPane',
44
- rect: new Rect(this.rect().width - this._defaultHandlePosition - 1, bodyHeight + scrollWidth),
45
- scrollableV: false,
46
- scrollableH: true,
131
+ view: 'Box',
132
+ rect: '0 0 100 100',
47
133
  anchors: 'left top right bottom',
48
- className: 'table-h-scroll',
49
- childViews: [
50
- {
51
- view: 'List',
52
- rect: new Rect(this.rect().width - this._defaultHandlePosition - 1, bodyHeight + scrollWidth),
53
- anchors: 'left top rect bottom'
54
- }
55
- ]
134
+ style: { overflow: 'hidden' },
135
+ rect: new Rect(this.rect().width - this._defaultHandlePosition - 1, bodyHeight),
136
+ childViews: {
137
+ view: 'ScrollPane',
138
+ rect: new Rect(this.rect().width - this._defaultHandlePosition - 1, bodyHeight + scrollWidth),
139
+ scrollableV: false,
140
+ scrollableH: true,
141
+ anchors: 'left top right bottom',
142
+ className: 'table-h-scroll',
143
+ childViews: [
144
+ {
145
+ view: 'List',
146
+ rect: new Rect(this.rect().width - this._defaultHandlePosition - 1, bodyHeight + scrollWidth),
147
+ anchors: 'left top right bottom'
148
+ }
149
+ ]
150
+ }
151
+
56
152
  }
57
153
  ]
58
154
  }
@@ -65,7 +161,8 @@ uki.view.declare('uki.more.view.SplitTable', uki.view.Table, function(base) {
65
161
  scrollableH: true,
66
162
  scrollableV: false,
67
163
  scrollH: true,
68
- className: 'table-h-scroll-bar'
164
+ className: 'table-h-scroll-bar',
165
+ childViews: { view: 'Box', rect: '1 1', anchors: 'left top' }
69
166
  }
70
167
  ]).appendTo(this);
71
168
 
@@ -74,6 +171,88 @@ uki.view.declare('uki.more.view.SplitTable', uki.view.Table, function(base) {
74
171
  this._horizontalScrollBar = uki('ScrollPane[className=table-h-scroll-bar]', this)[0];
75
172
  this._leftList = uki('List:eq(0)', this)[0];
76
173
  this._rightList = uki('List:eq(1)', this)[0];
77
- this._splitPane = uki('SplitPane', this)[0];
174
+ this._splitPane = uki('HSplitPane', this)[0];
175
+ this._leftHeader = uki('table.Header:eq(0)', this)[0];
176
+ this._rightHeader = uki('table.Header:eq(1)', this)[0];
177
+ this._rightHeaderContainer = uki('[className=table-header-container]', this)[0];
178
+ this._dummyScrollContents = uki('Box', this._horizontalScrollBar);
179
+
180
+ this._leftList._scrollableParent = this._verticalScroll;
181
+ this._rightList._scrollableParent = this._verticalScroll;
182
+ this._verticalScroll.bind('scroll', uki.proxy(this._leftList._scrollableParentScroll, this._leftList));
183
+ this._verticalScroll.bind('scroll', uki.proxy(this._rightList._scrollableParentScroll, this._rightList));
184
+
185
+ this._leftList.render(new uki.more.view.splitTable.Render(this._leftHeader));
186
+ this._rightList.render(new uki.more.view.splitTable.Render(this._rightHeader));
187
+ this._bindEvents();
188
+ };
189
+
190
+ this._bindEvents = function() {
191
+ this._splitPane.bind('handleMove', uki.proxy(this._syncHandlePosition, this, this._splitPane));
192
+ this._horizontalScroll.bind('scroll', uki.proxy(this._syncHScroll, this, this._horizontalScroll));
193
+ this._horizontalScrollBar.bind('scroll', uki.proxy(this._syncHScroll, this, this._horizontalScrollBar));
194
+ this._leftList.bind('selection', uki.proxy(this._syncSelection, this, this._leftList));
195
+ this._rightList.bind('selection', uki.proxy(this._syncSelection, this, this._rightList));
196
+ };
197
+
198
+ var updatingHandlePosition = false;
199
+ this._syncHandlePosition = function(source) {
200
+ if (updatingHandlePosition) return;
201
+ updatingHandlePosition = true;
202
+ var w, rect;
203
+ if (source == this._splitPane) {
204
+ w = this._splitPane.handlePosition() + 1;
205
+ this.columns()[0].width(w);
206
+ } else {
207
+ var w = this.columns()[0].width();
208
+ this._splitPane.handlePosition(w - 1).layout();
209
+ }
210
+
211
+ this._leftHeader.rect(new Rect(w, this._headerHeight)).layout();
212
+
213
+ rect = this._rightHeaderContainer.rect().clone();
214
+ rect.x = w;
215
+ rect.width = this._rect.width - w - uki.view.ScrollPane.initScrollWidth();
216
+ this._rightHeaderContainer.rect(rect).layout();
217
+ rect = this._horizontalScrollBar.rect().clone();
218
+ rect.x = w;
219
+ rect.width = this._rect.width - w - uki.view.ScrollPane.initScrollWidth();
220
+ this._horizontalScrollBar.rect(rect).layout();
221
+ updatingHandlePosition = false;
222
+ };
223
+
224
+ var updatingHScroll = false;
225
+ this._syncHScroll = function(source) {
226
+ if (updatingHScroll) return;
227
+ updatingHScroll = true;
228
+ var scroll, target = source == this._horizontalScroll ? this._horizontalScrollBar : this._horizontalScroll;
229
+ scroll = source.scrollLeft();
230
+ target.scrollLeft(scroll);
231
+ this._rightHeader.dom().style.marginLeft = -scroll + 'px';
232
+ updatingHScroll = false;
233
+ };
234
+
235
+ var updatingSelection = false;
236
+ this._syncSelection = function(source) {
237
+ if (updatingSelection) return;
238
+ updatingSelection = true;
239
+ var target = source == this._leftList ? this._rightList : this._leftList;
240
+ target.selectedIndexes(source.selectedIndexes());
241
+ updatingSelection = false;
78
242
  };
79
- });
243
+
244
+ this._updateTotalWidth = function() {
245
+ this._totalWidth = 0;
246
+ for (var i=1; i < this._columns.length; i++) {
247
+ this._totalWidth += this._columns[i].width();
248
+ };
249
+ this._rightHeader.minSize(new Size(this._totalWidth, 0));
250
+ this._rightList.minSize(new Size(this._totalWidth, this._rightList.minSize().height));
251
+ this._dummyScrollContents.rect(new Rect(this._totalWidth, 1)).parent().layout();
252
+ this._rightHeader.minSize(new Size(this._totalWidth, 0));
253
+ this._horizontalScroll.layout();
254
+ };
255
+
256
+ });
257
+
258
+ include('splitTable/render.js');
@@ -11,7 +11,7 @@ uki.more.view.treeList.Render = uki.newClass(uki.view.list.Render, new function(
11
11
  );
12
12
 
13
13
  this.initStyles = function() {
14
- uki.more.view.treeList.Render.prototype.classPrefix = 'treeList-' + uki.dom.guid++;
14
+ this.classPrefix = 'treeList-' + uki.dom.guid++;
15
15
  var style = new uki.theme.Template(
16
16
  '.${classPrefix}-row { color: #333; position:relative; padding-top:3px; } ' +
17
17
  '.${classPrefix}-toggle { overflow: hidden; position:absolute; left:-15px; top:5px; width: 10px; height:9px; } ' +
@@ -3,25 +3,20 @@ include('../view.js');
3
3
  // really basic tree list implementation
4
4
  uki.more.view.treeList = {};
5
5
 
6
- uki.more.view.TreeList = uki.newClass(uki.view.List, new function() {
7
- var Base = uki.view.List.prototype,
8
- proto = this;
9
-
10
- proto.typeName = function() { return 'uki.more.view.TreeList'; };
11
-
12
- proto._setup = function() {
6
+ uki.view.declare('uki.more.view.TreeList', uki.view.List, function(Base) {
7
+ this._setup = function() {
13
8
  Base._setup.call(this);
14
9
  this._render = new uki.more.view.treeList.Render();
15
10
  };
16
11
 
17
- proto.listData = Base.data;
12
+ this.listData = Base.data;
18
13
 
19
- proto.data = uki.newProp('_treeData', function(v) {
14
+ this.data = uki.newProp('_treeData', function(v) {
20
15
  this._treeData = v;
21
16
  this.listData(this._treeNodeToListData(v));
22
17
  });
23
18
 
24
- proto._treeNodeToListData = function(node, indent) {
19
+ this._treeNodeToListData = function(node, indent) {
25
20
  indent = indent || 0;
26
21
  return uki.map(node, function(row) {
27
22
  row.__indent = indent;
@@ -29,62 +24,94 @@ uki.more.view.TreeList = uki.newClass(uki.view.List, new function() {
29
24
  });
30
25
  };
31
26
 
32
- proto.toggle = function(index) {
27
+ this.toggle = function(index) {
33
28
  this._data[index].__opened ? this.close(index) : this.open(index);
34
29
  };
35
30
 
31
+ function offsetFrom (array, from, offset) {
32
+ for (var i = from; i < array.length; i++) {
33
+ array[i] += offset;
34
+ };
35
+ }
36
+
36
37
  function recursiveLength (item) {
37
38
  var children = item.children,
38
- length = children.length;
39
-
39
+ length = children.length;
40
+
40
41
  for (var i=0; i < children.length; i++) {
41
42
  if (children[i].__opened) length += recursiveLength(children[i]);
42
43
  };
43
44
  return length;
44
- }
45
-
46
- proto.open = function(index, _skipUpdate) {
47
- var selectedIndex = this._selectedIndex,
48
- item = this._data[index],
45
+ }
46
+
47
+ this._openSubElement = function(index) {
48
+ var item = this._data[index],
49
49
  children = item.children;
50
50
 
51
- if (!children || !children.length || (item.__opened && !_skipUpdate)) return 0;
51
+ if (!children || !children.length) return 0;
52
52
  var length = children.length;
53
-
53
+
54
54
  item.__opened = true;
55
55
  this._data.splice.apply(this._data, [index+1, 0].concat( this._treeNodeToListData(children, item.__indent + 1) ));
56
56
 
57
57
  for (var i=children.length - 1; i >= 0 ; i--) {
58
58
  if (this._data[index+1+i].__opened) {
59
- length += this.open(index+1+i, true);
59
+ length += this._openSubElement(index+1+i);
60
60
  }
61
61
  };
62
- if (!_skipUpdate) {
63
- this.listData(this._data);
64
- this.selectedIndex(selectedIndex <= index ? selectedIndex : selectedIndex + length);
65
- }
66
62
  return length;
67
63
  };
68
64
 
69
- proto.close = function(index) {
70
- var selectedIndex = this._selectedIndex,
71
- item = this._data[index],
72
- children = item.children;
65
+ this.open = function(index) {
66
+ if (this._data[index].__opened) return this;
67
+
68
+ var length = this._openSubElement(index),
69
+ positionInSelection = uki.binarySearch(index, this._selectedIndexes),
70
+ clickIndex = this._lastClickIndex,
71
+ indexes = this._selectedIndexes;
73
72
 
73
+ this.clearSelection(true);
74
+ offsetFrom(
75
+ indexes,
76
+ positionInSelection + (indexes[positionInSelection] == index ? 1 : 0),
77
+ length
78
+ );
79
+
80
+ this.listData(this._data);
81
+ this.selectedIndexes(indexes);
82
+ this._lastClickIndex = clickIndex > index ? clickIndex + length : clickIndex;
83
+ return this;
84
+ };
85
+
86
+ this.close = function(index) {
87
+ var item = this._data[index],
88
+ indexes = this._selectedIndexes,
89
+ children = item.children;
74
90
  if (!children || !children.length || !item.__opened) return;
91
+
75
92
  var length = recursiveLength(item);
76
-
93
+
77
94
  item.__opened = false;
78
95
  this._data.splice(index+1, length);
96
+
97
+ var positionInSelection = uki.binarySearch(index, indexes),
98
+ removeFrom = positionInSelection + (indexes[positionInSelection] == index ? 1 : 0),
99
+ toRemove = 0,
100
+ clickIndex = this._lastClickIndex;
101
+ while (indexes[removeFrom + toRemove] && indexes[removeFrom + toRemove] <= index + length) toRemove++;
102
+
103
+ this.clearSelection(true);
104
+ offsetFrom(indexes, removeFrom, -length);
105
+ if (toRemove > 0) {
106
+ indexes.splice(positionInSelection, toRemove);
107
+ }
108
+
79
109
  this.listData(this._data);
80
- this.selectedIndex(
81
- selectedIndex <= index ? selectedIndex :
82
- selectedIndex >= index + length ? index - length :
83
- index
84
- );
110
+ this.selectedIndexes(indexes);
111
+ this._lastClickIndex = clickIndex > index ? clickIndex - length : clickIndex;
85
112
  };
86
-
87
- proto._mousedown = function(e) {
113
+
114
+ this._mousedown = function(e) {
88
115
  if (e.domEvent.target.className.indexOf('toggle-tree') > -1) {
89
116
  var o = uki.dom.offset(this._dom),
90
117
  y = e.domEvent.pageY - o.y,
@@ -95,13 +122,13 @@ uki.more.view.TreeList = uki.newClass(uki.view.List, new function() {
95
122
  }
96
123
  };
97
124
 
98
- proto._keypress = function(e) {
125
+ this._keypress = function(e) {
99
126
  Base._keypress.call(this, e);
100
127
  e = e.domEvent;
101
128
  if (e.which == 39 || e.keyCode == 39) { // RIGHT
102
- this.open(this._selectedIndex);
129
+ this.open(this._lastClickIndex);
103
130
  } else if (e.which == 37 || e.keyCode == 37) { // LEFT
104
- this.close(this._selectedIndex);
131
+ this.close(this._lastClickIndex);
105
132
  }
106
133
  };
107
134
 
@@ -1,4 +1,4 @@
1
1
  include('uki-more/more/view/treeList.js');
2
- include('uki-more/more/view/multiselectList.js');
3
2
  include('uki-more/more/view/toggleButton.js');
4
3
  include('uki-more/more/view/radioButton.js');
4
+ include('uki-more/more/view/splitTable.js');
@@ -141,8 +141,16 @@
141
141
  return new uki.background.Css('#CCC');
142
142
  },
143
143
 
144
+ 'toolbar-popup-button-normal': function() {
145
+ return new uki.background.Css({ textAlign: 'left' });
146
+ },
147
+
148
+ 'toolbar-popup-button-down': function() {
149
+ return new uki.background.Css({ background: '#AAA', textAlign: 'left' });
150
+ },
151
+
144
152
  'toolbar-popup-button-hover': function() {
145
- return new uki.background.Css({ background: '#4086FF', color: '#FFF' });
153
+ return new uki.background.Css({ background: '#4086FF', color: '#FFF', textAlign: 'left' });
146
154
  },
147
155
 
148
156
 
@@ -240,10 +248,24 @@
240
248
  }
241
249
  },
242
250
 
251
+ templates: {
252
+ 'table-header-cell': function() {
253
+ return new uki.theme.Template(
254
+ '<div style="position:relative;border:1px solid #CCC;border-top:none;border-left:none;'+
255
+ '${style}" class="${className}">${data}</div>');
256
+ },
257
+
258
+ 'table-cell': function() {
259
+ return new uki.theme.Template(
260
+ '<div style="position:relative;border-right:1px solid #CCC;height:100%;'+
261
+ '${style}" class="${className}">${data}</div>');
262
+ }
263
+ },
264
+
243
265
  doms: {
244
- 'resizer': function(params) {
245
- var template = new uki.theme.Template('position:absolute;width:5px;top:0;height:${height}px;cursor:col-resize;cursor:ew-resize;z-index:101;background:url(' + uki.theme.imageSrc('x') + ')'),
246
- node = uki.createElement('div', template.render(params));
266
+ 'resizer': function(height) {
267
+ var template = new uki.theme.Template('position:absolute;width:5px;top:0;right:-3px;height:${height}px;cursor:col-resize;cursor:ew-resize;z-index:101;background:url(' + uki.theme.imageSrc('x') + ')'),
268
+ node = uki.createElement('div', template.render({height:height}));
247
269
 
248
270
  if (!node.style.cursor || window.opera) node.style.cursor = 'e-resize';
249
271
  return node;
@@ -317,6 +339,7 @@
317
339
 
318
340
  uki.theme.airport.backgrounds['input-focus'] = uki.theme.airport.backgrounds['button-focus'];
319
341
  uki.theme.airport.backgrounds['toolbar-popup'] = uki.theme.airport.backgrounds['popup-normal'];
342
+ uki.theme.airport.backgrounds['toolbar-popup-button-disabled'] = uki.theme.airport.backgrounds['toolbar-popup-button-normal'];
320
343
 
321
344
  uki.theme.register(uki.theme.airport);
322
345
  })();
@@ -12,7 +12,7 @@ uki.view.declare('uki.view.Label', uki.view.Base, function(Base) {
12
12
  };
13
13
 
14
14
  this._style = function(name, value) {
15
- if (value !== undefined && 'fontWeight fontSize textDecoration color'.indexOf(name) != -1) {
15
+ if (value !== undefined && 'font fontFamily fontWeight fontSize textDecoration color'.indexOf(name) != -1) {
16
16
  this._label.style[name] = value;
17
17
  }
18
18
  return Base._style.call(this, name, value);
@@ -36,11 +36,18 @@ uki.view.declare('uki.view.List', uki.view.Base, uki.view.Focusable, function(Ba
36
36
  this.clearSelection();
37
37
  this._data = d;
38
38
  this._packs[0].itemFrom = this._packs[0].itemTo = this._packs[1].itemFrom = this._packs[1].itemTo = 0;
39
- this._updateRectOnDataChnage();
39
+
40
+ var minWidth = this._minSize ? this._minSize.width : 0;
41
+ this.minSize(new Size(minWidth, this._rowHeight * this._data.length));
40
42
  this._relayoutParent();
41
43
  return this;
42
44
  };
43
45
 
46
+ this.relayout = function() {
47
+ this._packs[0].itemFrom = this._packs[0].itemTo = this._packs[1].itemFrom = this._packs[1].itemTo = 0;
48
+ this.layout();
49
+ };
50
+
44
51
  this.addRow = function(position, data) {
45
52
  this.clearSelection();
46
53
  this._data.splice(position, 0, data);
@@ -124,7 +131,9 @@ uki.view.declare('uki.view.List', uki.view.Base, uki.view.Focusable, function(Ba
124
131
  this.selectedIndexes(indexes);
125
132
  };
126
133
 
134
+ var updatingScroll = false;
127
135
  this._scrollableParentScroll = function() {
136
+ if (updatingScroll) return;
128
137
  if (this._throttle) {
129
138
  if (this._throttleStarted) return;
130
139
  this._throttleStarted = true;
@@ -148,12 +157,8 @@ uki.view.declare('uki.view.List', uki.view.Base, uki.view.Focusable, function(Ba
148
157
  };
149
158
 
150
159
 
151
- this._updateRectOnDataChnage = function() {
152
- this.rect(this._parentRect);
153
- };
154
-
155
160
  this.keyPressEvent = function() {
156
- var useKeyPress = /mozilla/i.test( ua ) && !(/(compatible|webkit)/i).test( ua );
161
+ var useKeyPress = root.opera || (/mozilla/i.test( ua ) && !(/(compatible|webkit)/i).test( ua ));
157
162
  return useKeyPress ? 'keypress' : 'keydown';
158
163
  };
159
164
 
@@ -213,11 +218,13 @@ uki.view.declare('uki.view.List', uki.view.Base, uki.view.Focusable, function(Ba
213
218
  nextIndex = -1;
214
219
  if (e.which == 38 || e.keyCode == 38) { // UP
215
220
  nextIndex = Math.max(0, this._lastClickIndex - 1);
221
+ e.preventDefault();
216
222
  } else if (e.which == 40 || e.keyCode == 40) { // DOWN
217
223
  nextIndex = Math.min(this._data.length-1, this._lastClickIndex + 1);
224
+ e.preventDefault();
218
225
  }
219
226
  if (nextIndex > -1 && nextIndex != this._lastClickIndex) {
220
- if (e.shiftKey) {
227
+ if (e.shiftKey && this._multiselect) {
221
228
  if (this.isSelected(nextIndex)) {
222
229
  this._toggleSelection(this._lastClickIndex);
223
230
  } else {
@@ -227,7 +234,6 @@ uki.view.declare('uki.view.List', uki.view.Base, uki.view.Focusable, function(Ba
227
234
  this.selectedIndex(nextIndex);
228
235
  }
229
236
  this._lastClickIndex = nextIndex;
230
- e.preventDefault();
231
237
  }
232
238
  };
233
239
 
@@ -264,11 +270,13 @@ uki.view.declare('uki.view.List', uki.view.Base, uki.view.Focusable, function(Ba
264
270
  var maxY, minY;
265
271
  maxY = (position+1)*this._rowHeight;
266
272
  minY = position*this._rowHeight;
273
+ updatingScroll = true;
267
274
  if (maxY >= this._visibleRect.maxY()) {
268
275
  this._scrollableParent.scroll(0, maxY - this._visibleRect.maxY());
269
276
  } else if (minY < this._visibleRect.y) {
270
277
  this._scrollableParent.scroll(0, minY - this._visibleRect.y);
271
278
  }
279
+ updatingScroll = false;
272
280
  this.layout();
273
281
  };
274
282
 
@@ -326,17 +334,6 @@ uki.view.declare('uki.view.List', uki.view.Base, uki.view.Focusable, function(Ba
326
334
  this._packs[1] = tmp;
327
335
  };
328
336
 
329
- this._normalizeRect = function(rect) {
330
- rect = Base._normalizeRect.call(this, rect);
331
- // if (rect.height != this._rowHeight * this._data.length) {
332
- // rect = new Rect(rect.x, rect.y, rect.width, this._rowHeight * this._data.length);
333
- // }
334
- if (rect.height < this._rowHeight * this._data.length) {
335
- rect = new Rect(rect.x, rect.y, rect.width, this._rowHeight * this._data.length);
336
- }
337
- return rect;
338
- };
339
-
340
337
  this._layoutDom = function(rect) {
341
338
  if (!this._scrollableParent) {
342
339
  this._scrollableParent = uki.view.scrollableParent(this);