uki 1.0.1 → 1.0.2
Sign up to get free protection for your applications and to get access to all the features.
- data/VERSION +1 -1
- data/bin/uki +53 -2
- data/frameworks/uki/README.rdoc +49 -7
- data/frameworks/uki/spec/unit/data/model.spec.js +16 -5
- data/frameworks/uki/spec/unit/dom.spec.js +1 -1
- data/frameworks/uki/spec/unit/utils.spec.js +1 -1
- data/frameworks/uki/src/uki-core/background/sliced9.js +1 -1
- data/frameworks/uki/src/uki-core/collection.js +5 -5
- data/frameworks/uki/src/uki-core/dom/dnd.js +4 -0
- data/frameworks/uki/src/uki-core/dom/event.js +15 -8
- data/frameworks/uki/src/uki-core/dom/w3cdnd.js +18 -3
- data/frameworks/uki/src/uki-core/dom.js +1 -3
- data/frameworks/uki/src/uki-core/uki.js +2 -1
- data/frameworks/uki/src/uki-core/utils.js +2 -2
- data/frameworks/uki/src/uki-core/view/base.js +4 -3
- data/frameworks/uki/src/uki-core/view/focusable.js +61 -41
- data/frameworks/uki/src/uki-core/view/observable.js +3 -2
- data/frameworks/uki/src/uki-core/view/styleable.js +6 -6
- data/frameworks/uki/src/uki-data/model.js +83 -17
- data/frameworks/uki/src/uki-data/observable.js +8 -5
- data/frameworks/uki/src/uki-more/more/view/treeList/render.js +4 -3
- data/frameworks/uki/src/uki-more/more/view/treeList.js +18 -7
- data/frameworks/uki/src/uki-view/view/checkbox.js +2 -0
- data/frameworks/uki/src/uki-view/view/flow.js +28 -9
- data/frameworks/uki/src/uki-view/view/list.js +59 -16
- data/frameworks/uki/src/uki-view/view/radio.js +2 -1
- data/frameworks/uki/src/uki-view/view/scrollPane.js +5 -6
- data/frameworks/uki/src/uki-view/view/slider.js +4 -4
- data/frameworks/uki/src/uki-view/view/splitPane.js +26 -29
- data/frameworks/uki/src/uki-view/view/table/column.js +6 -5
- data/frameworks/uki/src/uki-view/view/table/header.js +28 -18
- data/frameworks/uki/src/uki-view/view/table.js +41 -2
- data/frameworks/uki/src/uki-view/view/textField.js +2 -3
- data/lib/uki/project.rb +55 -15
- data/templates/controller.js.erb +5 -0
- data/templates/layout.js.erb +5 -0
- data/templates/myapp.js.erb +1 -2
- data/uki.gemspec +4 -2
- metadata +5 -3
@@ -33,11 +33,10 @@ uki.view.Styleable = new function() {
|
|
33
33
|
// };
|
34
34
|
// });
|
35
35
|
|
36
|
-
var probe = uki.createElement('div').style
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
});
|
36
|
+
var probe = uki.createElement('div').style;
|
37
|
+
uki.each(['userSelect', 'MozUserSelect', 'WebkitUserSelect'], function(i, name) {
|
38
|
+
if (typeof probe[name] == 'string') this._textSelectProp = name;
|
39
|
+
}, this);
|
41
40
|
|
42
41
|
/**
|
43
42
|
* Sets whether text of the view can be selected.
|
@@ -56,7 +55,7 @@ uki.view.Styleable = new function() {
|
|
56
55
|
} else {
|
57
56
|
uki.dom[state ? 'unbind' : 'bind'](this.dom(), 'selectstart', uki.dom.preventDefaultHandler);
|
58
57
|
}
|
59
|
-
this._dom.style.cursor = state ? '
|
58
|
+
this._dom.style.cursor = state ? '' : 'default';
|
60
59
|
return this;
|
61
60
|
};
|
62
61
|
|
@@ -64,6 +63,7 @@ uki.view.Styleable = new function() {
|
|
64
63
|
if (state === undefined) return this._dom.getAttribute('draggable');
|
65
64
|
this._dom.setAttribute('draggable', true);
|
66
65
|
this._dom.style.WebkitUserDrag = 'element';
|
66
|
+
return this;
|
67
67
|
};
|
68
68
|
|
69
69
|
/**#@-*/
|
@@ -1,28 +1,94 @@
|
|
1
1
|
include('observable.js');
|
2
2
|
|
3
|
+
/**
|
4
|
+
*
|
5
|
+
* @example
|
6
|
+
* myModel = uki.newClass(uki.data.Model, function() {
|
7
|
+
* uki.data.model.addField(this, ['name', 'age', 'sex']);
|
8
|
+
* })
|
9
|
+
*
|
10
|
+
* var m = new myModel({ age: 22, name: 'Jonh Smith', sex: 'm' })
|
11
|
+
* m.bind('change.sex', function() {
|
12
|
+
* alert('omg! wtf!');
|
13
|
+
* });
|
14
|
+
*
|
15
|
+
* m.bind('change', function(e) {
|
16
|
+
* console.log(e.fields);
|
17
|
+
* });
|
18
|
+
*
|
19
|
+
* m.name('Joe Black') // triggers 'change' and 'change.name'
|
20
|
+
* m.sex('w') // triggers'change' and 'change.sex'
|
21
|
+
*/
|
3
22
|
uki.data.Model = uki.newClass(uki.data.Observable, function(Observable) {
|
4
23
|
|
5
|
-
this.
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
24
|
+
this._fields = [];
|
25
|
+
|
26
|
+
this.init = function(values) {
|
27
|
+
this.update(values || {});
|
28
|
+
};
|
29
|
+
|
30
|
+
this.fields = function() {
|
31
|
+
return this._fields;
|
32
|
+
};
|
33
|
+
|
34
|
+
this.update = function(values) {
|
35
|
+
var fields = [], changes = {};
|
36
|
+
|
37
|
+
uki.each(values, function(name, value) {
|
38
|
+
var field = uki.isFunction(this[name]) ? '_' + name : name;
|
39
|
+
if (this[field] != value) {
|
40
|
+
changes[name] = true;
|
41
|
+
fields.push(name);
|
42
|
+
this[field] = value;
|
43
|
+
this.trigger('change.' + name, { model: this });
|
17
44
|
}
|
18
45
|
}, this);
|
19
46
|
|
20
|
-
this.
|
47
|
+
if (fields.length) this.trigger('change', {changes: changes, fields: fields, model: this});
|
21
48
|
return this;
|
22
49
|
};
|
23
50
|
|
24
|
-
|
25
|
-
|
26
|
-
|
51
|
+
});
|
52
|
+
|
53
|
+
uki.data.model = {
|
54
|
+
_newProp: function(name) {
|
55
|
+
return uki.newProp('_' + name, function(v) {
|
56
|
+
var changes = {};
|
57
|
+
changes[name] = v;
|
58
|
+
this.update(changes);
|
59
|
+
});
|
60
|
+
},
|
27
61
|
|
28
|
-
|
62
|
+
addFields: function(target, names) {
|
63
|
+
for (var i=0; i < names.length; i++) {
|
64
|
+
target[names[i]] = uki.data.model._newProp(names[i]);
|
65
|
+
}
|
66
|
+
// do not break prototypes
|
67
|
+
target._fields = names.concat(target._fields || []);
|
68
|
+
},
|
69
|
+
|
70
|
+
newLoader: function(name, options) {
|
71
|
+
return function(callback) {
|
72
|
+
callback = callback || uki.F;
|
73
|
+
if (this['loaded.' + name]) {
|
74
|
+
callback.call(this, this[name]());
|
75
|
+
} else {
|
76
|
+
this.bind('load.' + name, callback);
|
77
|
+
if (!this['loading.' + name]) {
|
78
|
+
this['loading.' + name] = true;
|
79
|
+
uki.ajax(uki.extend({
|
80
|
+
url: uki.isFunction(options.url) ? options.url.call(this) : options.url,
|
81
|
+
data: uki.isFunction(options.data) ? options.data.call(this) : options.data ? options.data : { id: this.id() },
|
82
|
+
success: uki.proxy(function(val) {
|
83
|
+
this['loading.' + name] = false;
|
84
|
+
this['loaded.' + name] = true;
|
85
|
+
options.setter ? options.setter.call(this, val) : this['_' + name] = val;
|
86
|
+
this.trigger('load.' + name, val);
|
87
|
+
this.unbind('load.' + name);
|
88
|
+
}, this)
|
89
|
+
}, options.ajaxOptions || {}));
|
90
|
+
}
|
91
|
+
}
|
92
|
+
};
|
93
|
+
}
|
94
|
+
};
|
@@ -5,6 +5,7 @@ include('data.js');
|
|
5
5
|
uki.data.Observable = {
|
6
6
|
bind: function(name, callback) {
|
7
7
|
var _this = this;
|
8
|
+
callback.huid = callback.huid || uki.guid++;
|
8
9
|
uki.each(name.split(' '), function(i, name) {
|
9
10
|
_this._observersFor(name).push(callback);
|
10
11
|
});
|
@@ -13,20 +14,22 @@ uki.data.Observable = {
|
|
13
14
|
unbind: function(name, callback) {
|
14
15
|
var _this = this;
|
15
16
|
uki.each(name.split(' '), function(i, name) {
|
16
|
-
_this._observers[name] = uki.grep(_this._observersFor(name), function(c) {
|
17
|
-
return c != callback;
|
17
|
+
_this._observers[name] = !callback ? [] : uki.grep(_this._observersFor(name), function(c) {
|
18
|
+
return c != callback && c.huid != callback.huid;
|
18
19
|
});
|
20
|
+
if (_this._observers[name]) delete _this._observers[name];
|
19
21
|
});
|
20
22
|
},
|
21
23
|
|
22
24
|
trigger: function(name/*, data1, data2*/) {
|
23
25
|
var attrs = Array.prototype.slice.call(arguments, 1);
|
24
|
-
uki.each(this._observersFor(name), function(i, callback) {
|
26
|
+
uki.each(this._observersFor(name, true), function(i, callback) {
|
25
27
|
callback.apply(this, attrs);
|
26
|
-
});
|
28
|
+
}, this);
|
27
29
|
},
|
28
30
|
|
29
|
-
_observersFor: function(name) {
|
31
|
+
_observersFor: function(name, skipCreate) {
|
32
|
+
if (skipCreate && (!this._observers || !this._observers[name])) return [];
|
30
33
|
if (!this._observers) this._observers = {};
|
31
34
|
if (!this._observers[name]) this._observers[name] = [];
|
32
35
|
return this._observers[name];
|
@@ -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
|
-
this.classPrefix = 'treeList-' + uki.
|
14
|
+
this.classPrefix = 'treeList-' + uki.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; } ' +
|
@@ -30,8 +30,9 @@ uki.more.view.treeList.Render = uki.newClass(uki.view.list.Render, new function(
|
|
30
30
|
|
31
31
|
this.render = function(row, rect, i) {
|
32
32
|
this.classPrefix || this.initStyles();
|
33
|
-
var text = row.data
|
34
|
-
|
33
|
+
var text = row.data,
|
34
|
+
children = uki.attr(row, 'children');
|
35
|
+
if (children && children.length) {
|
35
36
|
return this._parentTemplate.render({
|
36
37
|
text: text,
|
37
38
|
indent: row.__indent*18 + 22,
|
@@ -13,7 +13,16 @@ uki.view.declare('uki.more.view.TreeList', uki.view.List, function(Base) {
|
|
13
13
|
|
14
14
|
this.data = uki.newProp('_treeData', function(v) {
|
15
15
|
this._treeData = v;
|
16
|
-
this.
|
16
|
+
this._data = this._treeNodeToListData(v);
|
17
|
+
var children = this.listData(), opened = false;
|
18
|
+
for (var i=children.length - 1; i >= 0 ; i--) {
|
19
|
+
if (this._data[i].__opened) {
|
20
|
+
opened = true;
|
21
|
+
this._openSubElement(i);
|
22
|
+
}
|
23
|
+
};
|
24
|
+
this.listData(this._data);
|
25
|
+
if (opened) this.trigger('open');
|
17
26
|
});
|
18
27
|
|
19
28
|
this._treeNodeToListData = function(node, indent) {
|
@@ -35,7 +44,7 @@ uki.view.declare('uki.more.view.TreeList', uki.view.List, function(Base) {
|
|
35
44
|
}
|
36
45
|
|
37
46
|
function recursiveLength (item) {
|
38
|
-
var children = item
|
47
|
+
var children = uki.attr(item, 'children'),
|
39
48
|
length = children.length;
|
40
49
|
|
41
50
|
for (var i=0; i < children.length; i++) {
|
@@ -46,8 +55,8 @@ uki.view.declare('uki.more.view.TreeList', uki.view.List, function(Base) {
|
|
46
55
|
|
47
56
|
this._openSubElement = function(index) {
|
48
57
|
var item = this._data[index],
|
49
|
-
children = item
|
50
|
-
|
58
|
+
children = uki.attr(item, 'children');
|
59
|
+
|
51
60
|
if (!children || !children.length) return 0;
|
52
61
|
var length = children.length;
|
53
62
|
|
@@ -80,13 +89,14 @@ uki.view.declare('uki.more.view.TreeList', uki.view.List, function(Base) {
|
|
80
89
|
this.listData(this._data);
|
81
90
|
this.selectedIndexes(indexes);
|
82
91
|
this._lastClickIndex = clickIndex > index ? clickIndex + length : clickIndex;
|
92
|
+
this.trigger('open');
|
83
93
|
return this;
|
84
94
|
};
|
85
95
|
|
86
96
|
this.close = function(index) {
|
87
97
|
var item = this._data[index],
|
88
98
|
indexes = this._selectedIndexes,
|
89
|
-
children = item
|
99
|
+
children = uki.attr(item, 'children');
|
90
100
|
if (!children || !children.length || !item.__opened) return;
|
91
101
|
|
92
102
|
var length = recursiveLength(item);
|
@@ -109,12 +119,13 @@ uki.view.declare('uki.more.view.TreeList', uki.view.List, function(Base) {
|
|
109
119
|
this.listData(this._data);
|
110
120
|
this.selectedIndexes(indexes);
|
111
121
|
this._lastClickIndex = clickIndex > index ? clickIndex - length : clickIndex;
|
122
|
+
this.trigger('close');
|
112
123
|
};
|
113
124
|
|
114
125
|
this._mousedown = function(e) {
|
115
|
-
if (e.
|
126
|
+
if (e.target.className.indexOf('toggle-tree') > -1) {
|
116
127
|
var o = uki.dom.offset(this._dom),
|
117
|
-
y = e.
|
128
|
+
y = e.pageY - o.y,
|
118
129
|
p = y / this._rowHeight << 0;
|
119
130
|
this.toggle(p);
|
120
131
|
} else {
|
@@ -23,8 +23,10 @@ uki.view.declare('uki.view.Checkbox', uki.view.Button, function(Base) {
|
|
23
23
|
};
|
24
24
|
|
25
25
|
this.value = this.checked = uki.newProp('_checked', function(state) {
|
26
|
+
var changed = this._checked != !!state;
|
26
27
|
this._checked = !!state;
|
27
28
|
this._updateBg();
|
29
|
+
if (changed) this.trigger('change', {checked: this._checked, source: this});
|
28
30
|
});
|
29
31
|
|
30
32
|
this._mouseup = function(e) {
|
@@ -8,23 +8,41 @@ uki.view.declare('uki.view.VFlow', uki.view.Container, function(Base) {
|
|
8
8
|
|
9
9
|
this.hidePartlyVisible = uki.newProp('_hidePartlyVisible');
|
10
10
|
|
11
|
-
this.
|
11
|
+
this.resizeToContents = function(autosizeStr) {
|
12
|
+
this._resizeChildViews(this._rect);
|
13
|
+
return Base.resizeToContents.call(this, autosizeStr);
|
14
|
+
}
|
15
|
+
|
16
|
+
uki.each(['appendChild', 'removeChild', 'insertBefore'], function(i, name) {
|
17
|
+
this[name] = function(arg1, arg2) {
|
18
|
+
this._contentChanged = true;
|
19
|
+
return Base[name].call(this, arg1, arg2);
|
20
|
+
};
|
21
|
+
}, this)
|
22
|
+
|
23
|
+
this.layout = function() {
|
24
|
+
if (this._contentChanged) this._resizeChildViews(this._rect);
|
25
|
+
return Base.layout.call(this);
|
26
|
+
};
|
27
|
+
|
28
|
+
// resize in layout
|
29
|
+
this._resizeChildViews = function(oldRect) {
|
30
|
+
this._contentChanged = false;
|
12
31
|
var offset = 0, rect, view;
|
13
32
|
for (var i=0, childViews = this.childViews(); i < childViews.length; i++) {
|
14
33
|
view = childViews[i];
|
15
|
-
view.
|
34
|
+
view.parentResized(oldRect, this._rect);
|
35
|
+
view.rect().y = offset;
|
36
|
+
// view.rect(new Rect(view._rect.x, offset, view._rect.width, view._rect.height));
|
16
37
|
if (this._hidePartlyVisible) {
|
17
38
|
view.visible(view._rect.height + offset <= this._rect.height);
|
18
39
|
}
|
19
40
|
if (view.visible()) offset += view._rect.height;
|
20
41
|
};
|
21
|
-
Base._layoutChildViews.call(this);
|
22
42
|
};
|
23
43
|
});
|
24
44
|
|
25
|
-
uki.view.declare('uki.view.HFlow', uki.view.
|
26
|
-
this.hidePartlyVisible = uki.newProp('_hidePartlyVisible');
|
27
|
-
|
45
|
+
uki.view.declare('uki.view.HFlow', uki.view.VFlow, function(Base) {
|
28
46
|
this.contentsSize = function() {
|
29
47
|
var value = uki.reduce(0, this._childViews, function(sum, e) {
|
30
48
|
return sum + (e.visible() ? e.rect().width : 0);
|
@@ -32,17 +50,18 @@ uki.view.declare('uki.view.HFlow', uki.view.Container, function(Base) {
|
|
32
50
|
return new Size( value, this.contentsHeight() );
|
33
51
|
};
|
34
52
|
|
35
|
-
this.
|
53
|
+
this._resizeChildViews = function(oldRect) {
|
36
54
|
var offset = 0, rect, view;
|
37
55
|
for (var i=0, childViews = this.childViews(); i < childViews.length; i++) {
|
38
56
|
view = childViews[i];
|
39
|
-
view.
|
57
|
+
view.parentResized(oldRect, this._rect);
|
58
|
+
view.rect().x = offset;
|
59
|
+
// view.rect(new Rect(offset, view._rect.y, view._rect.width, view._rect.height));
|
40
60
|
if (this._hidePartlyVisible) {
|
41
61
|
view.visible(view._rect.width + offset <= this._rect.width);
|
42
62
|
}
|
43
63
|
if (view.visible()) offset += view._rect.width;
|
44
64
|
};
|
45
|
-
Base._layoutChildViews.call(this);
|
46
65
|
};
|
47
66
|
|
48
67
|
});
|
@@ -3,7 +3,7 @@ include('scrollPane.js');
|
|
3
3
|
uki.view.list = {};
|
4
4
|
uki.view.declare('uki.view.List', uki.view.Base, uki.view.Focusable, function(Base, Focusable) {
|
5
5
|
|
6
|
-
this._throttle =
|
6
|
+
this._throttle = 42; // do not try to render more often than every 42ms
|
7
7
|
this._visibleRectExt = 300; // extend visible rect by 300 px overflow
|
8
8
|
this._defaultBackground = 'theme(list)';
|
9
9
|
|
@@ -22,13 +22,15 @@ uki.view.declare('uki.view.List', uki.view.Base, uki.view.Focusable, function(Ba
|
|
22
22
|
return uki.theme.background('list', this._rowHeight);
|
23
23
|
};
|
24
24
|
|
25
|
-
uki.addProps(this, ['render', 'packSize', 'visibleRectExt', 'throttle', 'contentDraggable', 'lastClickIndex', 'multiselect']);
|
25
|
+
uki.addProps(this, ['render', 'packSize', 'visibleRectExt', 'throttle', 'contentDraggable', 'lastClickIndex', 'multiselect', 'lastClickIndex']);
|
26
26
|
|
27
27
|
this.rowHeight = uki.newProp('_rowHeight', function(val) {
|
28
28
|
this._rowHeight = val;
|
29
|
+
this.minSize(new Size(this.minSize().width, this._rowHeight * this._data.length));
|
29
30
|
if (this._background) this._background.detach();
|
30
31
|
this._background = null;
|
31
32
|
if (this.background()) this.background().attachTo(this);
|
33
|
+
this._relayoutParent();
|
32
34
|
});
|
33
35
|
|
34
36
|
this.data = function(d) {
|
@@ -37,8 +39,8 @@ uki.view.declare('uki.view.List', uki.view.Base, uki.view.Focusable, function(Ba
|
|
37
39
|
this._data = d;
|
38
40
|
this._packs[0].itemFrom = this._packs[0].itemTo = this._packs[1].itemFrom = this._packs[1].itemTo = 0;
|
39
41
|
|
40
|
-
|
41
|
-
this.
|
42
|
+
this.minSize(new Size(this.minSize().width, this._rowHeight * this._data.length));
|
43
|
+
this.trigger('selection', {source: this})
|
42
44
|
this._relayoutParent();
|
43
45
|
return this;
|
44
46
|
};
|
@@ -48,16 +50,51 @@ uki.view.declare('uki.view.List', uki.view.Base, uki.view.Focusable, function(Ba
|
|
48
50
|
this.layout();
|
49
51
|
};
|
50
52
|
|
53
|
+
this.contentsSize = function() {
|
54
|
+
return new Size(this.rect().width, this._rowHeight * this._data.length);
|
55
|
+
};
|
56
|
+
|
57
|
+
// used in search. should be fast
|
51
58
|
this.addRow = function(position, data) {
|
52
|
-
this.clearSelection();
|
53
59
|
this._data.splice(position, 0, data);
|
54
|
-
this.
|
60
|
+
var item = this._itemAt(position);
|
61
|
+
if (item) {
|
62
|
+
var container = doc.createElement('div');
|
63
|
+
|
64
|
+
container.innerHTML = this._rowTemplate.render({
|
65
|
+
height: this._rowHeight,
|
66
|
+
text: this._render.render(this._data[position], this._rowRect(position), position)
|
67
|
+
});
|
68
|
+
item.parentNode.insertBefore(container.firstChild, item);
|
69
|
+
if (position < this._packs[0].itemTo) {
|
70
|
+
this._packs[0].itemTo++;
|
71
|
+
this._packs[1].itemFrom++;
|
72
|
+
this._packs[1].itemTo++;
|
73
|
+
this._packs[1].dom.style.top = this._packs[1].itemFrom*this._rowHeight + 'px';
|
74
|
+
} else {
|
75
|
+
this._packs[1].itemTo++;
|
76
|
+
}
|
77
|
+
}
|
78
|
+
|
79
|
+
// offset selection
|
80
|
+
var selectionPosition = uki.binarySearch(position, this.selectedIndexes());
|
81
|
+
for (var i = selectionPosition; i < this._selectedIndexes.length; i++) {
|
82
|
+
this._selectedIndexes[i]++;
|
83
|
+
};
|
84
|
+
|
85
|
+
return this;
|
55
86
|
};
|
56
87
|
|
57
88
|
this.removeRow = function(position, data) {
|
58
|
-
this.clearSelection();
|
59
89
|
this._data.splice(position, 1);
|
60
90
|
this.data(this._data);
|
91
|
+
return this;
|
92
|
+
};
|
93
|
+
|
94
|
+
this.redrawRow = function(row) {
|
95
|
+
var item = this._itemAt(row);
|
96
|
+
if (item) item.innerHTML = this._render.render(this._data[row], this._rowRect(row), row);
|
97
|
+
return this;
|
61
98
|
};
|
62
99
|
|
63
100
|
this.selectedIndex = function(position) {
|
@@ -69,12 +106,13 @@ uki.view.declare('uki.view.List', uki.view.Base, uki.view.Focusable, function(Ba
|
|
69
106
|
|
70
107
|
this.selectedIndexes = function(indexes) {
|
71
108
|
if (indexes === undefined) return this._selectedIndexes;
|
109
|
+
var changed = indexes != this._selectedIndexes;
|
72
110
|
this.clearSelection(true);
|
73
111
|
this._selectedIndexes = indexes;
|
74
112
|
for (var i=0; i < this._selectedIndexes.length; i++) {
|
75
113
|
this._setSelected(this._selectedIndexes[i], true);
|
76
114
|
};
|
77
|
-
this.trigger('selection', {source: this});
|
115
|
+
if (changed) this.trigger('selection', {source: this});
|
78
116
|
return this;
|
79
117
|
};
|
80
118
|
|
@@ -120,6 +158,10 @@ uki.view.declare('uki.view.List', uki.view.Base, uki.view.Focusable, function(Ba
|
|
120
158
|
if (p > initialP) array.splice(initialP, p - initialP);
|
121
159
|
}
|
122
160
|
|
161
|
+
this._rowRect = function(p) {
|
162
|
+
return new Rect(0, p*this._rowHeight, this.rect().width, this._rowHeight);
|
163
|
+
};
|
164
|
+
|
123
165
|
this._toggleSelection = function(p) {
|
124
166
|
var indexes = [].concat(this._selectedIndexes);
|
125
167
|
var addTo = uki.binarySearch(p, indexes);
|
@@ -222,6 +264,9 @@ uki.view.declare('uki.view.List', uki.view.Base, uki.view.Focusable, function(Ba
|
|
222
264
|
} else if (e.which == 40 || e.keyCode == 40) { // DOWN
|
223
265
|
nextIndex = Math.min(this._data.length-1, this._lastClickIndex + 1);
|
224
266
|
e.preventDefault();
|
267
|
+
} else if (this._multiselect && (e.which == 97 || e.which == 65) && e.metaKey) {
|
268
|
+
e.preventDefault();
|
269
|
+
this.selectedIndexes(range(0, this._data.length -1));
|
225
270
|
}
|
226
271
|
if (nextIndex > -1 && nextIndex != this._lastClickIndex) {
|
227
272
|
if (e.shiftKey && this._multiselect) {
|
@@ -230,6 +275,7 @@ uki.view.declare('uki.view.List', uki.view.Base, uki.view.Focusable, function(Ba
|
|
230
275
|
} else {
|
231
276
|
this._toggleSelection(nextIndex);
|
232
277
|
}
|
278
|
+
this._scrollToPosition(nextIndex);
|
233
279
|
} else {
|
234
280
|
this.selectedIndex(nextIndex);
|
235
281
|
}
|
@@ -292,14 +338,12 @@ uki.view.declare('uki.view.List', uki.view.Base, uki.view.Focusable, function(Ba
|
|
292
338
|
this._rowTemplate = new uki.theme.Template('<div style="width:100%;height:${height}px;overflow:hidden;">${text}</div>')
|
293
339
|
|
294
340
|
this._renderPack = function(pack, itemFrom, itemTo) {
|
295
|
-
var html = [], position
|
296
|
-
rect = new Rect(0, itemFrom*this._rowHeight, this.rect().width, this._rowHeight);
|
341
|
+
var html = [], position;
|
297
342
|
for (i=itemFrom; i < itemTo; i++) {
|
298
343
|
html[html.length] = this._rowTemplate.render({
|
299
344
|
height: this._rowHeight,
|
300
|
-
text: this._render.render(this._data[i],
|
345
|
+
text: this._render.render(this._data[i], this._rowRect(i), i)
|
301
346
|
});
|
302
|
-
rect.y += this._rowHeight;
|
303
347
|
};
|
304
348
|
pack.dom.innerHTML = html.join('');
|
305
349
|
pack.itemFrom = itemFrom;
|
@@ -344,7 +388,7 @@ uki.view.declare('uki.view.List', uki.view.Base, uki.view.Focusable, function(Ba
|
|
344
388
|
scrollableParent = this._scrollableParent;
|
345
389
|
|
346
390
|
this._visibleRect = uki.view.visibleRect(this, scrollableParent);
|
347
|
-
|
391
|
+
if (this._focusTarget) this._focusTarget.style.top = this._visibleRect.y + 'px';
|
348
392
|
var prefferedPackSize = CEIL((this._visibleRect.height + this._visibleRectExt*2) / this._rowHeight),
|
349
393
|
|
350
394
|
minVisibleY = MAX(0, this._visibleRect.y - this._visibleRectExt),
|
@@ -355,7 +399,6 @@ uki.view.declare('uki.view.List', uki.view.Base, uki.view.Focusable, function(Ba
|
|
355
399
|
itemFrom, itemTo, startAt, updated = true;
|
356
400
|
|
357
401
|
Base._layoutDom.call(this, rect);
|
358
|
-
|
359
402
|
if (
|
360
403
|
maxVisibleY <= minRenderedY || minVisibleY >= maxRenderedY || // both packs below/above visible area
|
361
404
|
(maxVisibleY > maxRenderedY && this._packs[1].itemFrom * this._rowHeight > this._visibleRect.y && this._packs[1].itemTo > this._packs[1].itemFrom) || // need to render below, and pack 2 is not enough to cover
|
@@ -396,7 +439,7 @@ uki.view.declare('uki.view.List', uki.view.Base, uki.view.Focusable, function(Ba
|
|
396
439
|
} else {
|
397
440
|
updated = false;
|
398
441
|
}
|
399
|
-
if (updated && /MSIE 7/.test(ua)) this.dom().className += '';
|
442
|
+
if (updated && /MSIE 6|7/.test(ua)) this.dom().className += '';
|
400
443
|
};
|
401
444
|
|
402
445
|
this._bindToDom = function(name) {
|
@@ -419,7 +462,7 @@ uki.view.declare('uki.view.List', uki.view.Base, uki.view.Focusable, function(Ba
|
|
419
462
|
|
420
463
|
});
|
421
464
|
|
422
|
-
uki.Collection.addAttrs(['data','selectedIndex']);
|
465
|
+
uki.Collection.addAttrs(['data','selectedIndex', 'selectedIndexes', 'selectedRows']);
|
423
466
|
|
424
467
|
uki.view.declare('uki.view.ScrollableList', uki.view.ScrollPane, function(Base) {
|
425
468
|
|
@@ -13,9 +13,11 @@ include('checkbox.js');
|
|
13
13
|
});
|
14
14
|
|
15
15
|
this.value = this.checked = uki.newProp('_checked', function(state) {
|
16
|
+
var changed = this._checked != !!state;
|
16
17
|
this._checked = !!state;
|
17
18
|
if (state) manager.clearGroup(this);
|
18
19
|
this._updateBg();
|
20
|
+
if (changed) this.trigger('change', {checked: this._checked, source: this});
|
19
21
|
});
|
20
22
|
|
21
23
|
this._mouseup = function() {
|
@@ -23,7 +25,6 @@ include('checkbox.js');
|
|
23
25
|
this._down = false;
|
24
26
|
if (!this._checked && !this._disabled) {
|
25
27
|
this.checked(!this._checked);
|
26
|
-
this.trigger('change', {checked: this._checked, source: this});
|
27
28
|
}
|
28
29
|
}
|
29
30
|
});
|
@@ -52,12 +52,6 @@
|
|
52
52
|
if (dy) this.scrollTop(this.scrollTop() + dy);
|
53
53
|
};
|
54
54
|
|
55
|
-
uki.each(['appendChild', 'removeChild', 'insertBefore'], function(i, name) {
|
56
|
-
this[name] = function(arg1, arg2) {
|
57
|
-
return Base[name].call(this, arg1, arg2);
|
58
|
-
};
|
59
|
-
}, this);
|
60
|
-
|
61
55
|
uki.each(['scrollTop', 'scrollLeft'], function(i, name) {
|
62
56
|
this[name] = function(v) {
|
63
57
|
if (v == undefined) return this._dom[name];
|
@@ -86,6 +80,11 @@
|
|
86
80
|
this.trigger('resize', {oldRect: oldRect, newRect: this._rect, source: this});
|
87
81
|
return this;
|
88
82
|
};
|
83
|
+
|
84
|
+
this._createDom = function() {
|
85
|
+
Base._createDom.call(this);
|
86
|
+
if (ua.indexOf('Gecko/') > -1) this._dom.tabIndex = '-1';
|
87
|
+
};
|
89
88
|
|
90
89
|
this._recalcClientRects = function() {
|
91
90
|
initScrollWidth();
|
@@ -71,7 +71,7 @@ uki.view.declare('uki.view.Slider', uki.view.Base, uki.view.Focusable, function(
|
|
71
71
|
}, this);
|
72
72
|
|
73
73
|
this.bind('click', this._click);
|
74
|
-
this.bind(
|
74
|
+
this.bind(uki.view.List.prototype.keyPressEvent(), this._keypress);
|
75
75
|
};
|
76
76
|
|
77
77
|
this._mouseenter = function() {
|
@@ -90,10 +90,10 @@ uki.view.declare('uki.view.Slider', uki.view.Base, uki.view.Focusable, function(
|
|
90
90
|
this._cachedIndex = undefined;
|
91
91
|
};
|
92
92
|
|
93
|
-
this.
|
94
|
-
if (e.which == 39) {
|
93
|
+
this._keypress = function(e) {
|
94
|
+
if (e.which == 39 || e.keyCode == 39) {
|
95
95
|
this.value(this.value() + this._keyStep * (this._max - this._min));
|
96
|
-
} else if (e.which == 37) {
|
96
|
+
} else if (e.which == 37 || e.keyCode == 37) {
|
97
97
|
this.value(this.value() - this._keyStep * (this._max - this._min));
|
98
98
|
}
|
99
99
|
};
|