uki 1.0.1 → 1.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
1.0.
|
1
|
+
1.0.2
|
data/bin/uki
CHANGED
@@ -7,7 +7,7 @@ require 'commander/import'
|
|
7
7
|
require File.join(UKI_ROOT, 'lib', 'uki')
|
8
8
|
|
9
9
|
program :name, 'uki tools'
|
10
|
-
program :version,
|
10
|
+
program :version, File.read(File.join(UKI_ROOT, 'VERSION'))
|
11
11
|
program :description, 'uki development tools'
|
12
12
|
|
13
13
|
|
@@ -63,6 +63,40 @@ command :'new model' do |c|
|
|
63
63
|
end
|
64
64
|
end
|
65
65
|
|
66
|
+
command :'new layout' do |c|
|
67
|
+
c.syntax = 'uki new layout <name>'
|
68
|
+
c.summary = 'Create uki layout'
|
69
|
+
c.description = "Create template for uki layout with given <name>
|
70
|
+
and add include to the project file"
|
71
|
+
c.example "Create myapp.layout.editor()", "uki new layout editor"
|
72
|
+
c.example "Create view in arbitary package", "uki new layout mypackage.editor"
|
73
|
+
|
74
|
+
c.when_called do |args, options|
|
75
|
+
path = args.shift or raise 'Layout name required'
|
76
|
+
project = Uki::Project.new('.')
|
77
|
+
path = "#{project.name}.layout.#{path}"
|
78
|
+
project.create_function 'layout.js', path
|
79
|
+
say "Layout #{path} created"
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
command :'new controller' do |c|
|
84
|
+
c.syntax = 'uki new controller <name>'
|
85
|
+
c.summary = 'Create uki controller'
|
86
|
+
c.description = "Create template for uki controller with given <name>
|
87
|
+
and add include to the project file"
|
88
|
+
c.example "Create myapp.controller.editor()", "uki new controller editor"
|
89
|
+
c.example "Create view in arbitary package", "uki new controller mypackage.editor"
|
90
|
+
|
91
|
+
c.when_called do |args, options|
|
92
|
+
path = args.shift or raise 'Controller name required'
|
93
|
+
project = Uki::Project.new('.')
|
94
|
+
path = "#{project.name}.controller.#{path}"
|
95
|
+
project.create_function 'controller.js', path
|
96
|
+
say "Controller #{path} created"
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
66
100
|
command :run do |c|
|
67
101
|
c.syntax = 'uki run [host[:port]]'
|
68
102
|
c.summary = 'Run development server'
|
@@ -96,7 +130,24 @@ command :build do |c|
|
|
96
130
|
target = args.shift || 'build'
|
97
131
|
project = Uki::Project.new('.')
|
98
132
|
project.build target, :compile => !option.nocompiler
|
99
|
-
say "Build complete at
|
133
|
+
say "Build complete at '#{target}'"
|
134
|
+
end
|
135
|
+
end
|
136
|
+
|
137
|
+
command :ie_images do |c|
|
138
|
+
c.syntax = 'uki ie_images [file]'
|
139
|
+
c.summary = 'Creates image files for IE6,7'
|
140
|
+
c.description = 'Creates image files for IE6,7 from
|
141
|
+
data urls in the theme file.
|
142
|
+
|
143
|
+
[file] defaults to <project_name>/theme.js
|
144
|
+
'
|
145
|
+
c.when_called do |args, option|
|
146
|
+
project = Uki::Project.new('.')
|
147
|
+
target = args.shift || File.join(project.name, 'theme.js')
|
148
|
+
place = project.ie_images target
|
149
|
+
say "IE images are at #{place}"
|
100
150
|
end
|
151
|
+
|
101
152
|
end
|
102
153
|
|
data/frameworks/uki/README.rdoc
CHANGED
@@ -1,22 +1,64 @@
|
|
1
1
|
= UKI – simple UiKit for complex Web apps
|
2
|
-
Uki is a
|
3
|
-
|
4
|
-
user interface toolkit for desktop-like web applications.
|
5
|
-
It comes with
|
6
|
-
a rich view-component library
|
7
|
-
ranging from Sliders to Grids and SplitPanes.
|
2
|
+
Uki is a JavaScript user interface toolkit for desktop-like web applications.
|
3
|
+
It comes with a rich view-component library ranging from Sliders to Grids and SplitPanes.
|
8
4
|
|
9
5
|
uki({ view: 'Button', text: 'Click me', rect: '10 10 100 24' }).attachTo( window );
|
10
6
|
|
11
7
|
uki('Button[text^=Click]').click(function() { alert(this.text()); });
|
12
8
|
|
9
|
+
|
10
|
+
== All you have to know in 5 minutes
|
11
|
+
1. Uki interfaces are created from Views the same way web pages are created from DOM nodes.
|
12
|
+
Views even behave similar to DOM nodes. You can appendView, insertBefore, access parentView etc.
|
13
|
+
panel.appendView(button)
|
14
|
+
Examples of views: Slider, SplitPane or Table
|
15
|
+
2. View have attributes. You can read them by calling attrname() without params and write with
|
16
|
+
attrname(newValue).
|
17
|
+
label.text('Lorem') // set text to a label
|
18
|
+
label.text() == 'Lorem' // get text
|
19
|
+
splitPane.handlePosition(300) // move the split pane handle to 300px
|
20
|
+
3. You can create Views with uki() function.
|
21
|
+
Once created view can be attached to any block DOM container with attachTo()
|
22
|
+
uki({ view: 'Label', text: 'Lorem', ... more attributes ... }).attachTo( window )
|
23
|
+
4. You can find attached views using css-like selectors.
|
24
|
+
uki('Label') // find all labels on page
|
25
|
+
uki('Box[name=main] > Label') // find all immediate descendant Labels in a box with name = "main"
|
26
|
+
5. uki() calls return Collection of Views. This is similar to jQuery('expression') result. You can
|
27
|
+
access individual views with [index]. You can manipulate all views at the same
|
28
|
+
time with a number of collection methods (http://ukijs.org/docs/symbols/uki.Collection.html)
|
29
|
+
uki('Label')[3] // get 3-d found label
|
30
|
+
6. Events are bound to Views (not individual DOM nodes) with the bind() function
|
31
|
+
uki('Label')[0].bind('click', function() { handle the event here }) // bind click to the first label
|
32
|
+
uki('Label').bind('click', function() { handle the event here }) // bind click to all labels
|
33
|
+
uki('Label').unbind('click') // unbind all click handlers from all labels
|
34
|
+
7. Views are laid out with initial position and resize rules. Initial position is set with the rect property
|
35
|
+
button.rect('50 20 100 22') // set left = 50px, top = 20px, width = 100px, height = 22px
|
36
|
+
Resize rules are set with the anchors property:
|
37
|
+
button.anchors('left top') // stay at the left top when container resizes
|
38
|
+
button.anchors('right bottom') // move with the bottom right corner of the container
|
39
|
+
button.anchors('left top right') // stay at the top, resize width with the container
|
40
|
+
You can pass both rect and anchors to the uki() function:
|
41
|
+
uki({ view: 'Button', rect: '50 20 100 22', anchors: 'left top right' })
|
42
|
+
8. You can change visual appearance of the views with themes. Theme is basically a collection of
|
43
|
+
resources like images, styled dom nodes and backgrounds. You can find an example of one
|
44
|
+
at http://github.com/voloko/uki/blob/master/src/uki-theme/airport.js
|
45
|
+
9. If your adding uki to existing project then it is better to simply add
|
46
|
+
<script src='http://static.ukijs.org/pkg/0.1.3/uki.gz.js'></script>
|
47
|
+
to your pages and it will work. If you start a new one you might try
|
48
|
+
uki-tools (http://github.com/voloko/uki-tools)
|
49
|
+
10. See the available resources in Links section and have fun
|
50
|
+
|
51
|
+
|
52
|
+
|
53
|
+
|
13
54
|
== Links
|
14
55
|
* API docs at http://ukijs.org/docs/
|
15
56
|
* Google group http://groups.google.com/group/ukijs
|
16
|
-
* Code examples at http://
|
57
|
+
* Code examples at http://ukijs.org/examples/
|
17
58
|
* Development docs and tutorial at http://wiki.github.com/voloko/uki/
|
18
59
|
* Google wave in 100 lines of code example: http://ukijs.org/examples/core-examples/wave
|
19
60
|
|
61
|
+
|
20
62
|
== Contribute
|
21
63
|
To install development server
|
22
64
|
1. Install ruby http://ruby-lang.org
|
@@ -9,7 +9,7 @@ describe 'uki.data.Model'
|
|
9
9
|
end
|
10
10
|
|
11
11
|
it 'should update model'
|
12
|
-
model.
|
12
|
+
model.update({ firstName: 'John', lastName: 'Smith' })
|
13
13
|
model.firstName.should.be 'John'
|
14
14
|
model.lastName.should.be 'Smith'
|
15
15
|
end
|
@@ -19,11 +19,22 @@ describe 'uki.data.Model'
|
|
19
19
|
e.fields.should.eql ['name']
|
20
20
|
e.changes.name.should.not.be_null
|
21
21
|
});
|
22
|
-
model.
|
22
|
+
model.update({ name: 'something' });
|
23
23
|
end
|
24
24
|
|
25
|
-
it 'should
|
26
|
-
model.
|
27
|
-
model.
|
25
|
+
it 'should allow accesor methods'
|
26
|
+
uki.data.model.addFields(model, ['firstName', 'lastName'])
|
27
|
+
model.update({ firstName: 'John', lastName: 'Smith' })
|
28
|
+
model.firstName().should.be 'John'
|
29
|
+
model.lastName().should.be 'Smith'
|
30
|
+
end
|
31
|
+
|
32
|
+
it 'should trigger change with accessor methods'
|
33
|
+
uki.data.model.addFields(model, ['firstName', 'lastName'])
|
34
|
+
model.bind('change', function(e) {
|
35
|
+
e.fields.should.eql ['firstName']
|
36
|
+
e.changes.firstName.should.be_true
|
37
|
+
});
|
38
|
+
model.firstName('something')
|
28
39
|
end
|
29
40
|
end
|
@@ -9,7 +9,7 @@ describe 'uki.dom'
|
|
9
9
|
|
10
10
|
it 'should create stylesheets'
|
11
11
|
x = uki.createElement('div')
|
12
|
-
x.className = 'test' + uki.
|
12
|
+
x.className = 'test' + uki.guid++
|
13
13
|
uki.dom.createStylesheet('.' + x.className + ' { display: inline !important; }')
|
14
14
|
uki.dom.probe(x, function() {
|
15
15
|
uki.dom.computedStyle(x).display.should.be 'inline'
|
@@ -52,7 +52,7 @@ uki.background.Sliced9 = uki.newClass(new function() {
|
|
52
52
|
|
53
53
|
/** @ignore */
|
54
54
|
function img (setting, style) {
|
55
|
-
return uki.imageHTML(setting[0], setting[1], setting[2], ' ondragstart="return false;" galleryimg="no" style="-webkit-user-drag:none;position:absolute;' + style + '"');
|
55
|
+
return uki.imageHTML(setting[0], setting[1], setting[2], ' ondragstart="return false;" galleryimg="no" style="-webkit-user-drag:none;-webkit-user-select:none;-moz-user-select:none;position:absolute;' + style + '"');
|
56
56
|
}
|
57
57
|
|
58
58
|
/** @ignore */
|
@@ -62,9 +62,9 @@ uki.fn = uki.Collection.prototype = new function() {
|
|
62
62
|
*/
|
63
63
|
this.attr = function( name, value ) {
|
64
64
|
if (value !== undefined) {
|
65
|
-
this.
|
66
|
-
uki.attr( this, name, value );
|
67
|
-
}
|
65
|
+
for (var i=0; i < this.length; i++) {
|
66
|
+
uki.attr( this[i], name, value );
|
67
|
+
};
|
68
68
|
return this;
|
69
69
|
} else {
|
70
70
|
return this[0] ? uki.attr( this[0], name ) : '';
|
@@ -167,7 +167,7 @@ uki.fn = uki.Collection.prototype = new function() {
|
|
167
167
|
@name uki.Collection#focusable */
|
168
168
|
/** @function
|
169
169
|
@name uki.Collection#style */
|
170
|
-
uki.Collection.addAttrs('dom html text background value rect checked anchors childViews typeName id name visible disabled focusable style draggable textSelectable'.split(' '));
|
170
|
+
uki.Collection.addAttrs('dom html text background value rect checked anchors childViews typeName id name visible disabled focusable style draggable textSelectable width height minX maxX minY maxY left top x y'.split(' '));
|
171
171
|
|
172
172
|
/** @function
|
173
173
|
@name uki.Collection#parent */
|
@@ -267,7 +267,7 @@ uki.fn = uki.Collection.prototype = new function() {
|
|
267
267
|
this.bind(name, handler);
|
268
268
|
} else {
|
269
269
|
for (var i=0; i < this.length; i++) {
|
270
|
-
this[i].trigger(name);
|
270
|
+
this[i][name] ? this[i][name]() : this[i].trigger(name);
|
271
271
|
};
|
272
272
|
}
|
273
273
|
return this;
|
@@ -54,6 +54,7 @@ var dragEndEvents = 'mouseup ' + (dnd.nativeDnD ? ' dragend' : '');
|
|
54
54
|
// if (window.attachEvent && !window.opera) dragEndEvents += ' mouseleave';
|
55
55
|
|
56
56
|
function startGesture (el) {
|
57
|
+
if (dnd.draggable) return;
|
57
58
|
dnd.draggable = el;
|
58
59
|
uki.dom.bind(doc, 'mousemove scroll', draggesture);
|
59
60
|
uki.dom.bind(doc, dragEndEvents, draggestureend);
|
@@ -68,6 +69,7 @@ function stopGesture () {
|
|
68
69
|
}
|
69
70
|
|
70
71
|
function draggesturestart (e) {
|
72
|
+
e = new uki.dom.Event(e);
|
71
73
|
e.type = 'draggesturestart';
|
72
74
|
uki.dom.handler.apply(this, arguments);
|
73
75
|
if (!e.isDefaultPrevented()) {
|
@@ -77,6 +79,7 @@ function draggesturestart (e) {
|
|
77
79
|
}
|
78
80
|
|
79
81
|
function draggesture (e) {
|
82
|
+
e = new uki.dom.Event(e);
|
80
83
|
e.type = 'draggesture';
|
81
84
|
e.dragOffset = (new Point(e.pageX, e.pageY)).offset(dnd.position);
|
82
85
|
uki.dom.handler.apply(dnd.draggable, arguments);
|
@@ -84,6 +87,7 @@ function draggesture (e) {
|
|
84
87
|
}
|
85
88
|
|
86
89
|
function draggestureend (e) {
|
90
|
+
e = new uki.dom.Event(e);
|
87
91
|
e.type = 'draggestureend';
|
88
92
|
e.dragOffset = (new Point(e.pageX, e.pageY)).offset(dnd.position);
|
89
93
|
uki.dom.handler.apply(dnd.draggable, arguments);
|
@@ -48,9 +48,9 @@ uki.extend(uki.dom, /** @lends uki.dom */ {
|
|
48
48
|
if ( el.setInterval && el != window )
|
49
49
|
el = window;
|
50
50
|
|
51
|
-
listener.huid = listener.huid || uki.
|
51
|
+
listener.huid = listener.huid || uki.guid++;
|
52
52
|
|
53
|
-
var id = el[expando] = el[expando] || uki.
|
53
|
+
var id = el[expando] = el[expando] || uki.guid++,
|
54
54
|
handler = uki.dom.handlers[id] = uki.dom.handlers[id] || function() {
|
55
55
|
uki.dom.handler.apply(arguments.callee.elem, arguments);
|
56
56
|
},
|
@@ -76,13 +76,18 @@ uki.extend(uki.dom, /** @lends uki.dom */ {
|
|
76
76
|
|
77
77
|
unbind: function(el, types, listener) {
|
78
78
|
var id = el[expando],
|
79
|
-
huid = listener.huid,
|
79
|
+
huid = listener && listener.huid,
|
80
80
|
i, type;
|
81
|
-
|
81
|
+
if (types) {
|
82
|
+
types = types.split(' ');
|
83
|
+
} else {
|
84
|
+
types = [];
|
85
|
+
uki.each(uki.dom.bound[id] || [], function(k, v) { types.push(k); });
|
86
|
+
}
|
82
87
|
for (i=0; i < types.length; i++) {
|
83
88
|
type = types[i];
|
84
|
-
if (!
|
85
|
-
uki.dom.bound[id][type] = uki.grep(uki.dom.bound[id][type], function(h) { return h.huid !== huid; });
|
89
|
+
if (!id || !uki.dom.bound[id] || !uki.dom.bound[id][type]) continue;
|
90
|
+
uki.dom.bound[id][type] = listener ? uki.grep(uki.dom.bound[id][type], function(h) { return h.huid !== huid; }) : [];
|
86
91
|
|
87
92
|
if (uki.dom.bound[id][type].length == 0) {
|
88
93
|
var handler = uki.dom.handlers[id];
|
@@ -103,8 +108,10 @@ uki.extend(uki.dom, /** @lends uki.dom */ {
|
|
103
108
|
handlers = uki.dom.bound[id],
|
104
109
|
i;
|
105
110
|
|
106
|
-
|
107
|
-
|
111
|
+
if (!e.domEvent) {
|
112
|
+
e = new uki.dom.Event(e);
|
113
|
+
e = uki.dom.fix( e );
|
114
|
+
}
|
108
115
|
|
109
116
|
if (!id || !handlers || !handlers[type]) return;
|
110
117
|
|
@@ -178,9 +178,19 @@ include('event.js');
|
|
178
178
|
|
179
179
|
var handler = function(e) {
|
180
180
|
if (dnd.dataTransfer && retriggering) {
|
181
|
+
e = new uki.dom.Event(e);
|
181
182
|
e.type = source;
|
182
183
|
e.dataTransfer = dnd.dataTransfer;
|
184
|
+
if (source == 'dragover') {
|
185
|
+
dnd.__canDrop = false;
|
186
|
+
} else {
|
187
|
+
stopW3Cdrag(this);
|
188
|
+
if (!dnd.__canDrop) return;
|
189
|
+
}
|
183
190
|
uki.dom.handler.apply(this, arguments);
|
191
|
+
if (e.isDefaultPrevented()) {
|
192
|
+
dnd.__canDrop = true;
|
193
|
+
}
|
184
194
|
}
|
185
195
|
};
|
186
196
|
|
@@ -211,6 +221,7 @@ include('event.js');
|
|
211
221
|
e.dataTransfer = new uki.dom.DataTransferWrapper(dataTransfer);
|
212
222
|
uki.dom.handler.apply(this, arguments);
|
213
223
|
dataTransfer.effectAllowed = e.dataTransfer.effectAllowed;
|
224
|
+
dataTransfer.dropEffect = e.dataTransfer.dropEffect;
|
214
225
|
}
|
215
226
|
|
216
227
|
function startW3Cdrag (element) {
|
@@ -218,14 +229,16 @@ include('event.js');
|
|
218
229
|
}
|
219
230
|
|
220
231
|
function stopW3Cdrag (element) {
|
232
|
+
if (!dnd.dataTransfer) return;
|
221
233
|
dnd.dataTransfer.cleanup();
|
222
234
|
dnd.dragOver = dnd.dataTransfer = dnd.target = null;
|
223
235
|
uki.dom.unbind( element, 'draggestureend', dragend );
|
224
236
|
}
|
225
237
|
|
226
238
|
function dragenter (e) {
|
227
|
-
if (!dnd.dataTransfer || e.domEvent.
|
228
|
-
e
|
239
|
+
if (!dnd.dataTransfer || e.domEvent.__dragEntered || !retriggering) return;
|
240
|
+
e = new uki.dom.Event(e);
|
241
|
+
e.domEvent.__dragEntered = true;
|
229
242
|
if (dnd.dragOver == this) return;
|
230
243
|
dnd.dragOver = this;
|
231
244
|
e.type = 'dragenter';
|
@@ -234,7 +247,8 @@ include('event.js');
|
|
234
247
|
|
235
248
|
function drag (e) {
|
236
249
|
if (retriggering) {
|
237
|
-
if (!e.domEvent.
|
250
|
+
if (!e.domEvent.__dragEntered && dnd.dragOver) {
|
251
|
+
e = new uki.dom.Event(e);
|
238
252
|
e.type = 'dragleave';
|
239
253
|
uki.dom.handler.apply(dnd.dragOver, arguments);
|
240
254
|
dnd.dragOver = null;
|
@@ -262,6 +276,7 @@ include('event.js');
|
|
262
276
|
} else {
|
263
277
|
return;
|
264
278
|
}
|
279
|
+
e = new uki.dom.Event(e);
|
265
280
|
uki.dom.handler.apply(this, arguments);
|
266
281
|
if (e.isDefaultPrevented()) {
|
267
282
|
stopW3Cdrag(this);
|
@@ -8,8 +8,6 @@ include('utils.js');
|
|
8
8
|
* @author voloko
|
9
9
|
*/
|
10
10
|
uki.dom = {
|
11
|
-
guid: 1,
|
12
|
-
|
13
11
|
/**
|
14
12
|
* Convenience wrapper around document.createElement
|
15
13
|
* Creates dom element with given tagName, cssText and innerHTML
|
@@ -23,7 +21,7 @@ uki.dom = {
|
|
23
21
|
var e = doc.createElement(tagName);
|
24
22
|
if (cssText) e.style.cssText = cssText;
|
25
23
|
if (innerHTML) e.innerHTML = innerHTML;
|
26
|
-
e[expando] = uki.
|
24
|
+
e[expando] = uki.guid++;
|
27
25
|
return e;
|
28
26
|
},
|
29
27
|
|
@@ -58,7 +58,7 @@ var utils = {
|
|
58
58
|
result = function() {
|
59
59
|
return fn.apply(context, args.concat(slice.call(arguments, 0)));
|
60
60
|
};
|
61
|
-
result.huid = fn.huid = fn.huid || uki.
|
61
|
+
result.huid = fn.huid = fn.huid || uki.guid++;
|
62
62
|
return result;
|
63
63
|
},
|
64
64
|
|
@@ -107,7 +107,7 @@ var utils = {
|
|
107
107
|
'"': '"',
|
108
108
|
"'": '''
|
109
109
|
};
|
110
|
-
return html.replace(/[&<>\"\']/g, function(c) { return trans[c]; });
|
110
|
+
return (html + '').replace(/[&<>\"\']/g, function(c) { return trans[c]; });
|
111
111
|
},
|
112
112
|
|
113
113
|
/**
|
@@ -286,8 +286,9 @@ uki.view.declare('uki.view.Base', uki.view.Observable, uki.view.Styleable, funct
|
|
286
286
|
if (s === undefined) return this[prop] || new Size();
|
287
287
|
this[prop] = Size.create(s);
|
288
288
|
this.rect(this._parentRect);
|
289
|
-
|
290
|
-
|
289
|
+
this._dom.style[name + 'Width'] = this[prop].width ? this[prop].width + PX : '';
|
290
|
+
this._dom.style[name + 'Height'] = this[prop].height ? this[prop].height + PX : '';
|
291
|
+
return this;
|
291
292
|
};
|
292
293
|
}, this);
|
293
294
|
|
@@ -426,7 +427,7 @@ uki.view.declare('uki.view.Base', uki.view.Observable, uki.view.Styleable, funct
|
|
426
427
|
@name uki.view.Base#left */
|
427
428
|
/** @function
|
428
429
|
@name uki.view.Base#top */
|
429
|
-
uki.each(['width', 'height', 'minX', 'maxX', 'minY', 'maxY', 'left', 'top'], function(index, attr) {
|
430
|
+
uki.each(['width', 'height', 'minX', 'maxX', 'minY', 'maxY', 'x', 'y', 'left', 'top'], function(index, attr) {
|
430
431
|
this[attr] = function(value) {
|
431
432
|
if (value === undefined) return uki.attr(this.rect(), attr);
|
432
433
|
uki.attr(this.rect(), attr, value);
|
@@ -4,40 +4,48 @@ include('observable.js');
|
|
4
4
|
/**
|
5
5
|
* @class
|
6
6
|
*/
|
7
|
-
uki.view.Focusable = /** @lends uki.view.Focusable.prototype */
|
7
|
+
uki.view.Focusable = new function() {/** @lends uki.view.Focusable.prototype */
|
8
|
+
|
8
9
|
// dom: function() {
|
9
10
|
// return null; // should implement
|
10
11
|
// },
|
11
|
-
_focusable
|
12
|
+
this._focusable = true; // default value
|
13
|
+
this._focusOnClick = true;
|
14
|
+
|
15
|
+
this.focusOnClick = uki.newProp('_focusOnClick');
|
12
16
|
|
13
|
-
focusable
|
17
|
+
this.focusable = uki.newProp('_focusable', function(v) {
|
14
18
|
this._focusable = v;
|
15
|
-
this.
|
19
|
+
if (v) this._initFocusable();
|
20
|
+
this._updateFocusable();
|
16
21
|
}),
|
17
22
|
|
18
|
-
disabled
|
23
|
+
this.disabled = uki.newProp('_disabled', function(d) {
|
24
|
+
var changed = d !== !!this._disabled;
|
19
25
|
this._disabled = d;
|
20
26
|
if (d) this.blur();
|
21
|
-
this.
|
22
|
-
if (this._updateBg) this._updateBg();
|
27
|
+
this._updateFocusable();
|
28
|
+
if (changed && this._updateBg) this._updateBg();
|
23
29
|
}),
|
24
30
|
|
25
|
-
|
26
|
-
if (this._focusTarget)
|
27
|
-
|
28
|
-
|
31
|
+
this._updateFocusable = function() {
|
32
|
+
if (this._preCreatedFocusTarget || !this._focusTarget) return;
|
33
|
+
|
34
|
+
if (this._focusable && !this._disabled) {
|
35
|
+
this._focusTarget.style.display = 'block';
|
36
|
+
} else {
|
37
|
+
this._focusTarget.style.display = 'none';
|
29
38
|
}
|
30
39
|
},
|
31
40
|
|
32
|
-
_initFocusable
|
33
|
-
this._focusTarget
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
this.
|
39
|
-
this.
|
40
|
-
this._focusTarget.hideFocus = true;
|
41
|
+
this._initFocusable = function(preCreatedFocusTarget) {
|
42
|
+
if ((!preCreatedFocusTarget && !this._focusable) || this._focusTarget) return;
|
43
|
+
this._focusTarget = preCreatedFocusTarget;
|
44
|
+
this._preCreatedFocusTarget = preCreatedFocusTarget;
|
45
|
+
|
46
|
+
if (!preCreatedFocusTarget) {
|
47
|
+
this._focusTarget = uki.createElement('input', 'position:absolute;left:-9999px;top:0;width:1px;height:1px;');
|
48
|
+
this.dom().appendChild(this._focusTarget);
|
41
49
|
}
|
42
50
|
this._hasFocus = false;
|
43
51
|
this._firstFocus = true;
|
@@ -45,48 +53,60 @@ uki.view.Focusable = /** @lends uki.view.Focusable.prototype */ {
|
|
45
53
|
uki.dom.bind(this._focusTarget, 'focus', uki.proxy(function(e) {
|
46
54
|
if (!this._hasFocus) this._focus(e);
|
47
55
|
}, this));
|
56
|
+
|
48
57
|
uki.dom.bind(this._focusTarget, 'blur', uki.proxy(function(e) {
|
49
|
-
if (this._hasFocus)
|
58
|
+
if (this._hasFocus) {
|
59
|
+
this._hasFocus = false;
|
60
|
+
setTimeout(uki.proxy(function() { // wait for mousedown refocusing
|
61
|
+
if (!this._hasFocus) this._blur();
|
62
|
+
}, this), 1);
|
63
|
+
}
|
50
64
|
}, this));
|
51
65
|
|
52
|
-
if (!
|
53
|
-
|
54
|
-
try { this.focus(); } catch (e) {};
|
55
|
-
}, this), 1);
|
66
|
+
if (!preCreatedFocusTarget) this.bind('mousedown', function(e) {
|
67
|
+
if (this._focusOnClick) this.focus();
|
56
68
|
});
|
57
|
-
|
69
|
+
this._updateFocusable();
|
70
|
+
}
|
58
71
|
|
59
|
-
_focus
|
72
|
+
this._focus = function(e) {
|
60
73
|
this._hasFocus = true;
|
61
74
|
this._firstFocus = false;
|
62
|
-
}
|
75
|
+
}
|
63
76
|
|
64
|
-
_blur
|
77
|
+
this._blur = function(e) {
|
65
78
|
this._hasFocus = false;
|
66
|
-
}
|
79
|
+
}
|
67
80
|
|
68
|
-
focus
|
69
|
-
|
70
|
-
if (
|
71
|
-
|
81
|
+
this.focus = function() {
|
82
|
+
if (this._focusable && !this._disabled) {
|
83
|
+
if (!this._hasFocus) this._focus();
|
84
|
+
var target = this._focusTarget;
|
85
|
+
setTimeout(function() {
|
86
|
+
try {
|
87
|
+
target.focus();
|
88
|
+
} catch(e) { }
|
89
|
+
target = null;
|
90
|
+
}, 1);
|
91
|
+
}
|
72
92
|
return this;
|
73
93
|
},
|
74
94
|
|
75
|
-
blur
|
95
|
+
this.blur = function() {
|
76
96
|
try {
|
77
97
|
this._focusTarget.blur();
|
78
98
|
} catch(e) {}
|
79
99
|
return this;
|
80
|
-
}
|
100
|
+
}
|
81
101
|
|
82
|
-
hasFocus
|
102
|
+
this.hasFocus = function() {
|
83
103
|
return this._hasFocus;
|
84
|
-
}
|
104
|
+
}
|
85
105
|
|
86
|
-
_bindToDom
|
106
|
+
this._bindToDom = function(name) {
|
87
107
|
if (!this._focusTarget || 'keyup keydown keypress focus blur'.indexOf(name) == -1) return false;
|
88
|
-
|
89
|
-
return uki.view.Observable._bindToDom.call(this, name, this.
|
108
|
+
|
109
|
+
return uki.view.Observable._bindToDom.call(this, name, this._focusTarget);
|
90
110
|
}
|
91
111
|
|
92
112
|
|
@@ -9,6 +9,7 @@ uki.view.Observable = /** @lends uki.view.Observable.prototype */ {
|
|
9
9
|
// },
|
10
10
|
|
11
11
|
bind: function(name, callback) {
|
12
|
+
callback.huid = callback.huid || uki.guid++;
|
12
13
|
uki.each(name.split(' '), function(i, name) {
|
13
14
|
if (!this._bound(name)) this._bindToDom(name);
|
14
15
|
this._observersFor(name).push(callback);
|
@@ -18,8 +19,8 @@ uki.view.Observable = /** @lends uki.view.Observable.prototype */ {
|
|
18
19
|
|
19
20
|
unbind: function(name, callback) {
|
20
21
|
uki.each(name.split(' '), function(i, name) {
|
21
|
-
this._observers[name] = uki.grep(this.
|
22
|
-
return observer != callback;
|
22
|
+
this._observers[name] = !callback ? [] : uki.grep(this._observersFor(name, true), function(observer) {
|
23
|
+
return observer != callback && observer.huid != callback.huid;
|
23
24
|
});
|
24
25
|
if (this._observers[name].length == 0) {
|
25
26
|
this._unbindFromDom(name);
|