uki 1.1.1 → 1.1.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.
Files changed (144) hide show
  1. data/VERSION +1 -1
  2. data/bin/uki +1 -1
  3. data/frameworks/uki/README.rdoc +1 -1
  4. data/frameworks/uki/examples/core-examples/controls/controls.js +6 -6
  5. data/frameworks/uki/examples/core-examples/flow/flow.js +4 -4
  6. data/frameworks/uki/examples/core-examples/linearGradient/gradient.svg +11 -0
  7. data/frameworks/uki/examples/core-examples/linearGradient/linearGradient.js +87 -0
  8. data/frameworks/uki/examples/core-examples/popup/popup.js +23 -10
  9. data/frameworks/uki/examples/core-examples/resizeToContents/resizeToContents.js +12 -1
  10. data/frameworks/uki/examples/core-examples/slider/slider.js +1 -1
  11. data/frameworks/uki/examples/core-examples/splitPaneExtended/splitPaneExtended.js +1 -1
  12. data/frameworks/uki/examples/core-examples/table/table.js +19 -2
  13. data/frameworks/uki/examples/core-examples/wave/wave-theme.js +1 -1
  14. data/frameworks/uki/examples/core-examples/wave/wave.js +1 -1
  15. data/frameworks/uki/examples/more-examples/radioButton/radioButton.js +3 -3
  16. data/frameworks/uki/examples/more-examples/select/select.js +35 -0
  17. data/frameworks/uki/examples/touch-examples/scrollPane/scrollPane.js +53 -0
  18. data/frameworks/uki/spec/unit/background.spec.js +1 -1
  19. data/frameworks/uki/spec/unit/selector.spec.js +28 -12
  20. data/frameworks/uki/spec/unit/utils.spec.js +14 -0
  21. data/frameworks/uki/src/uki-core.js +3 -1
  22. data/frameworks/uki/src/uki-core/after.js +57 -0
  23. data/frameworks/uki/src/uki-core/attachment.js +15 -6
  24. data/frameworks/uki/src/uki-core/background.js +4 -3
  25. data/frameworks/uki/src/uki-core/background/css.js +1 -0
  26. data/frameworks/uki/src/uki-core/background/cssBox.js +5 -3
  27. data/frameworks/uki/src/uki-core/background/linearGradient.js +112 -0
  28. data/frameworks/uki/src/uki-core/background/multi.js +2 -2
  29. data/frameworks/uki/src/uki-core/background/rows.js +1 -0
  30. data/frameworks/uki/src/uki-core/background/sliced9.js +5 -2
  31. data/frameworks/uki/src/uki-core/builder.js +5 -4
  32. data/frameworks/uki/src/uki-core/collection.js +18 -13
  33. data/frameworks/uki/src/uki-core/dom/browser.js +114 -0
  34. data/frameworks/uki/src/uki-core/dom/event.js +3 -0
  35. data/frameworks/uki/src/uki-core/image.js +1 -26
  36. data/frameworks/uki/src/uki-core/selector.js +5 -0
  37. data/frameworks/uki/src/uki-core/theme.js +24 -23
  38. data/frameworks/uki/src/uki-core/theme/template.js +1 -1
  39. data/frameworks/uki/src/uki-core/uki.js +7 -4
  40. data/frameworks/uki/src/uki-core/utils.js +51 -26
  41. data/frameworks/uki/src/uki-core/view.js +6 -3
  42. data/frameworks/uki/src/uki-core/view/base.js +16 -1
  43. data/frameworks/uki/src/uki-core/view/container.js +15 -5
  44. data/frameworks/uki/src/uki-core/view/focusable.js +17 -4
  45. data/frameworks/uki/src/uki-core/view/observable.js +15 -2
  46. data/frameworks/uki/src/uki-core/view/styleable.js +4 -11
  47. data/frameworks/uki/src/uki-data/ajax.js +4 -30
  48. data/frameworks/uki/src/uki-data/json.js +191 -0
  49. data/frameworks/uki/src/uki-data/localStore.js +37 -0
  50. data/frameworks/uki/src/uki-data/model.js +1 -1
  51. data/frameworks/uki/src/uki-more.js +4 -0
  52. data/frameworks/uki/src/uki-more/more/background.js +2 -0
  53. data/frameworks/uki/src/uki-more/more/color.js +168 -0
  54. data/frameworks/uki/src/uki-more/more/utils.js +5 -12
  55. data/frameworks/uki/src/uki-more/more/view.js +3 -1
  56. data/frameworks/uki/src/uki-more/more/view/form.js +30 -0
  57. data/frameworks/uki/src/uki-more/more/view/hTile.js +59 -0
  58. data/frameworks/uki/src/uki-more/more/view/nativeButton.js +3 -0
  59. data/frameworks/uki/src/uki-more/more/view/nativeCheckbox.js +38 -0
  60. data/frameworks/uki/src/uki-more/more/view/nativeControl.js +40 -0
  61. data/frameworks/uki/src/uki-more/more/view/nativeInput.js +78 -0
  62. data/frameworks/uki/src/uki-more/more/view/nativeSelect.js +29 -0
  63. data/frameworks/uki/src/uki-more/more/view/radioButton.js +1 -1
  64. data/frameworks/uki/src/uki-more/more/view/select-theme.js +55 -0
  65. data/frameworks/uki/src/uki-more/more/view/select.js +208 -0
  66. data/frameworks/uki/src/uki-theme/airport.js +145 -88
  67. data/frameworks/uki/src/uki-theme/airport/i/table/a-down.png +0 -0
  68. data/frameworks/uki/src/uki-theme/airport/i/table/a-up.png +0 -0
  69. data/frameworks/uki/src/uki-touch.js +2 -0
  70. data/frameworks/uki/src/uki-touch/touch.js +1 -0
  71. data/frameworks/uki/src/uki-touch/touch/const.js +24 -0
  72. data/frameworks/uki/src/uki-touch/touch/setup.js +52 -0
  73. data/frameworks/uki/src/uki-touch/touch/view.js +4 -0
  74. data/frameworks/uki/src/uki-touch/touch/view/scrollPane.js +505 -0
  75. data/frameworks/uki/src/uki-touch/touch/view/scrollableList.js +27 -0
  76. data/frameworks/uki/src/uki-view/view/box.js +9 -0
  77. data/frameworks/uki/src/uki-view/view/button.js +36 -1
  78. data/frameworks/uki/src/uki-view/view/checkbox.js +32 -3
  79. data/frameworks/uki/src/uki-view/view/flow.js +37 -9
  80. data/frameworks/uki/src/uki-view/view/image.js +14 -1
  81. data/frameworks/uki/src/uki-view/view/label.js +72 -11
  82. data/frameworks/uki/src/uki-view/view/list.js +143 -13
  83. data/frameworks/uki/src/uki-view/view/list/render.js +1 -0
  84. data/frameworks/uki/src/uki-view/view/popup.js +46 -2
  85. data/frameworks/uki/src/uki-view/view/radio.js +19 -4
  86. data/frameworks/uki/src/uki-view/view/scrollPane.js +91 -33
  87. data/frameworks/uki/src/uki-view/view/slider.js +67 -54
  88. data/frameworks/uki/src/uki-view/view/splitPane.js +102 -9
  89. data/frameworks/uki/src/uki-view/view/table.js +59 -2
  90. data/frameworks/uki/src/uki-view/view/table/column.js +45 -17
  91. data/frameworks/uki/src/uki-view/view/table/header.js +40 -12
  92. data/frameworks/uki/src/uki-view/view/table/render.js +4 -0
  93. data/frameworks/uki/src/uki-view/view/textField.js +75 -21
  94. data/frameworks/uki/src/uki-view/view/toolbar.js +16 -0
  95. data/lib/uki/builder.rb +1 -1
  96. data/lib/uki/include_js.rb +2 -2
  97. data/lib/uki/project.rb +14 -14
  98. data/templates/index.html.erb +2 -2
  99. data/templates/myapp.js.erb +2 -2
  100. data/uki.gemspec +34 -48
  101. metadata +44 -47
  102. data/frameworks/uki/src/uki-core/dom/nativeLayout.js +0 -18
  103. data/frameworks/uki/src/uki-theme/airport/i/button/down-c.gif +0 -0
  104. data/frameworks/uki/src/uki-theme/airport/i/button/down-c.png +0 -0
  105. data/frameworks/uki/src/uki-theme/airport/i/button/down-h.gif +0 -0
  106. data/frameworks/uki/src/uki-theme/airport/i/button/down-h.png +0 -0
  107. data/frameworks/uki/src/uki-theme/airport/i/button/down-m.png +0 -0
  108. data/frameworks/uki/src/uki-theme/airport/i/button/down-v.png +0 -0
  109. data/frameworks/uki/src/uki-theme/airport/i/button/focusRing-c.png +0 -0
  110. data/frameworks/uki/src/uki-theme/airport/i/button/focusRing-h.png +0 -0
  111. data/frameworks/uki/src/uki-theme/airport/i/button/focusRing-m.png +0 -0
  112. data/frameworks/uki/src/uki-theme/airport/i/button/focusRing-v.png +0 -0
  113. data/frameworks/uki/src/uki-theme/airport/i/button/focusRing.png +0 -0
  114. data/frameworks/uki/src/uki-theme/airport/i/button/hover-c.gif +0 -0
  115. data/frameworks/uki/src/uki-theme/airport/i/button/hover-c.png +0 -0
  116. data/frameworks/uki/src/uki-theme/airport/i/button/hover-h.gif +0 -0
  117. data/frameworks/uki/src/uki-theme/airport/i/button/hover-h.png +0 -0
  118. data/frameworks/uki/src/uki-theme/airport/i/button/hover-m.png +0 -0
  119. data/frameworks/uki/src/uki-theme/airport/i/button/hover-v.png +0 -0
  120. data/frameworks/uki/src/uki-theme/airport/i/button/hover.png +0 -0
  121. data/frameworks/uki/src/uki-theme/airport/i/button/normal-c.gif +0 -0
  122. data/frameworks/uki/src/uki-theme/airport/i/button/normal-c.png +0 -0
  123. data/frameworks/uki/src/uki-theme/airport/i/button/normal-h.gif +0 -0
  124. data/frameworks/uki/src/uki-theme/airport/i/button/normal-h.png +0 -0
  125. data/frameworks/uki/src/uki-theme/airport/i/button/normal-m.png +0 -0
  126. data/frameworks/uki/src/uki-theme/airport/i/button/normal-v.png +0 -0
  127. data/frameworks/uki/src/uki-theme/airport/i/button/normal.png +0 -0
  128. data/frameworks/uki/src/uki-theme/airport/i/panel/dark-h.gif +0 -0
  129. data/frameworks/uki/src/uki-theme/airport/i/panel/dark-h.png +0 -0
  130. data/frameworks/uki/src/uki-theme/airport/i/panel/dark-m.png +0 -0
  131. data/frameworks/uki/src/uki-theme/airport/i/panel/dark.png +0 -0
  132. data/frameworks/uki/src/uki-theme/airport/i/popup/normal.png +0 -0
  133. data/frameworks/uki/src/uki-theme/airport/i/shadow/large-c.png +0 -0
  134. data/frameworks/uki/src/uki-theme/airport/i/shadow/large-h.png +0 -0
  135. data/frameworks/uki/src/uki-theme/airport/i/shadow/large-m.png +0 -0
  136. data/frameworks/uki/src/uki-theme/airport/i/shadow/large-v.png +0 -0
  137. data/frameworks/uki/src/uki-theme/airport/i/shadow/large.png +0 -0
  138. data/frameworks/uki/src/uki-theme/airport/i/slider/bar-m.gif +0 -0
  139. data/frameworks/uki/src/uki-theme/airport/i/slider/bar-m.png +0 -0
  140. data/frameworks/uki/src/uki-theme/airport/i/slider/bar-v.gif +0 -0
  141. data/frameworks/uki/src/uki-theme/airport/i/slider/bar-v.png +0 -0
  142. data/frameworks/uki/src/uki-theme/airport/i/slider/bar.png +0 -0
  143. data/frameworks/uki/src/uki-theme/airport/i/slider/focus.png +0 -0
  144. data/frameworks/uki/src/uki-theme/airport/i/slider/handle.gif +0 -0
@@ -3,6 +3,7 @@ include('../list.js');
3
3
  /**
4
4
  * Flyweight view rendering
5
5
  * Used in lists, tables, grids
6
+ * @class
6
7
  */
7
8
  uki.view.list.Render = uki.newClass({
8
9
  init: function() {},
@@ -1,3 +1,11 @@
1
+ /**
2
+ * Popup
3
+ *
4
+ * @author voloko
5
+ * @name uki.view.Popup
6
+ * @class
7
+ * @extends uki.view.Container
8
+ */
1
9
  uki.view.declare('uki.view.Popup', uki.view.Container, function(Base) {
2
10
 
3
11
  this._setup = function() {
@@ -16,8 +24,28 @@ uki.view.declare('uki.view.Popup', uki.view.Container, function(Base) {
16
24
  this.hideOnClick(true);
17
25
  };
18
26
 
27
+ /**
28
+ * @function
29
+ * @name uki.view.Popup#offset
30
+ */
31
+ /**
32
+ * @function
33
+ * @name uki.view.Popup#relativeTo
34
+ */
35
+ /**
36
+ * @function
37
+ * @name uki.view.Popup#horizontal
38
+ */
39
+ /**
40
+ * @function
41
+ * @name uki.view.Popup#flipOnResize
42
+ */
19
43
  uki.addProps(this, ['offset', 'relativeTo', 'horizontal', 'flipOnResize']);
20
44
 
45
+ /**
46
+ * @function
47
+ * @name uki.view.Popup#hideOnClick
48
+ */
21
49
  this.hideOnClick = function(state) {
22
50
  if (state === undefined) return this._clickHandler;
23
51
  if (state != !!this._clickHandler) {
@@ -38,6 +66,10 @@ uki.view.declare('uki.view.Popup', uki.view.Container, function(Base) {
38
66
  return this;
39
67
  };
40
68
 
69
+ /**
70
+ * @function
71
+ * @name uki.view.Popup#toggle
72
+ */
41
73
  this.toggle = function() {
42
74
  if (this.parent() && this.visible()) {
43
75
  this.hide();
@@ -46,6 +78,10 @@ uki.view.declare('uki.view.Popup', uki.view.Container, function(Base) {
46
78
  }
47
79
  };
48
80
 
81
+ /**
82
+ * @function
83
+ * @name uki.view.Popup#show
84
+ */
49
85
  this.show = function() {
50
86
  this.visible(true);
51
87
  if (!this.parent()) {
@@ -57,6 +93,10 @@ uki.view.declare('uki.view.Popup', uki.view.Container, function(Base) {
57
93
  this.trigger('toggle', { source: this });
58
94
  };
59
95
 
96
+ /**
97
+ * @function
98
+ * @name uki.view.Popup#hide
99
+ */
60
100
  this.hide = function() {
61
101
  this.visible(false);
62
102
  this.trigger('toggle', { source: this });
@@ -91,14 +131,18 @@ uki.view.declare('uki.view.Popup', uki.view.Container, function(Base) {
91
131
 
92
132
  if (this._anchors & ANCHOR_RIGHT) {
93
133
  position.x = relativeOffset.x + relativeRect.width - (this._horizontal ? 0 : rect.width) + hOffset;
94
- } else {
134
+ } else if (this._anchors & ANCHOR_LEFT) {
95
135
  position.x = relativeOffset.x - (this._horizontal ? rect.width : 0) - hOffset;
136
+ } else {
137
+ position.x = relativeOffset.x + ((relativeRect.width - rect.width) >> 1) - hOffset;
96
138
  }
97
139
 
98
140
  if (this._anchors & ANCHOR_BOTTOM) {
99
141
  position.y = relativeOffset.y + (this._horizontal ? relativeRect.height : 0) - rect.height - vOffset;
100
- } else {
142
+ } else if (this._anchors & ANCHOR_TOP) {
101
143
  position.y = relativeOffset.y + (this._horizontal ? 0 : relativeRect.height) + vOffset;
144
+ } else {
145
+ position.y = relativeOffset.y + ((relativeRect.height - rect.height) >> 1) + vOffset;
102
146
  }
103
147
 
104
148
  return new Rect(position.x, position.y, rect.width, rect.height);
@@ -1,23 +1,34 @@
1
1
  include('checkbox.js');
2
2
 
3
3
  (function() {
4
+ /**
5
+ * Radio button
6
+ *
7
+ * @author voloko
8
+ * @name uki.view.Radio
9
+ * @class
10
+ * @extends uki.view.Checkbox
11
+ */
4
12
  var manager = uki.view.declare('uki.view.Radio', uki.view.Checkbox, function(base) {
5
13
 
6
14
  this._backgroundPrefix = 'radio-';
7
15
 
16
+ /**
17
+ * @function
18
+ * @param {String} group
19
+ * @name uki.view.Popup#hide
20
+ */
8
21
  this.group = uki.newProp('_group', function(g) {
9
22
  manager.unregisterGroup(this);
10
23
  this._group = g;
11
24
  manager.registerGroup(this);
12
- manager.clearGroup(this);
25
+ if (this.checked()) manager.clearGroup(this);
13
26
  });
14
27
 
15
28
  this.value = this.checked = uki.newProp('_checked', function(state) {
16
- var changed = this._checked != !!state;
17
29
  this._checked = !!state;
18
30
  if (state) manager.clearGroup(this);
19
31
  this._updateBg();
20
- if (changed) this.trigger('change', {checked: this._checked, source: this});
21
32
  });
22
33
 
23
34
  this._mouseup = function() {
@@ -25,6 +36,7 @@ include('checkbox.js');
25
36
  this._down = false;
26
37
  if (!this._checked && !this._disabled) {
27
38
  this.checked(!this._checked);
39
+ this.trigger('change', { checked: this._checked, source: this });
28
40
  }
29
41
  }
30
42
  });
@@ -51,7 +63,10 @@ include('checkbox.js');
51
63
  manager.clearGroup = function(radio) {
52
64
  uki.each(manager.groups[radio.group()] || [], function(i, registered) {
53
65
  if (registered == radio) return;
54
- if (registered.checked()) registered.checked(false);
66
+ if (registered.checked()) {
67
+ registered.checked(false);
68
+ this.trigger('change', { checked: false, source: registered });
69
+ }
55
70
  });
56
71
  };
57
72
 
@@ -19,39 +19,77 @@
19
19
  }
20
20
 
21
21
  /**
22
- * Scroll pane. Pane with scrollbars with content overflowing the borders.
23
- * Works consistently across all supported browsers.
24
- */
22
+ * Scroll pane.
23
+ * Pane with scrollbars with content overflowing the borders.
24
+ * Works consistently across all supported browsers.
25
+ *
26
+ * @author voloko
27
+ * @name uki.view.ScrollPane
28
+ * @class
29
+ * @extends uki.view.Container
30
+ */
25
31
  uki.view.declare('uki.view.ScrollPane', uki.view.Container, function(Base) {
26
- this.typeName = function() {
27
- return 'uki.view.ScrollPane';
28
- };
29
-
32
+ uki.extend(this, {
33
+ _scrollableY: true,
34
+ _scrollableX: false,
35
+ _scrollY: false,
36
+ _scrollX: false,
37
+ _sbY: false,
38
+ _sbX: false
39
+ });
40
+
30
41
  this._setup = function() {
31
42
  Base._setup.call(this);
32
43
 
33
- uki.extend(this, {
34
- _clientRect: this.rect().clone(), // rect with scroll bars excluded
35
- _rectForChild: this.rect().clone(),
36
- _scrollableV: true,
37
- _scrollableH: false,
38
- _scrollV: false,
39
- _scrollH: false,
40
- _sbV: false,
41
- _sbH: false
42
- });
44
+ this._clientRect = this.rect().clone();
45
+ this._rectForChild = this.rect().clone();
43
46
  };
44
47
 
45
- uki.addProps(this, ['scrollableV', 'scrollableH', 'scrollH', 'scrollV']);
48
+ /**
49
+ * @function
50
+ * @name uki.view.ScrollPane#scrollableY
51
+ */
52
+ /**
53
+ * @function
54
+ * @name uki.view.ScrollPane#scrollableX
55
+ */
56
+ /**
57
+ * @function
58
+ * @name uki.view.ScrollPane#scrollX
59
+ */
60
+ /**
61
+ * @function
62
+ * @name uki.view.ScrollPane#scrollY
63
+ */
64
+ uki.addProps(this, ['scrollableY', 'scrollableX', 'scrollX', 'scrollY']);
65
+ this.scrollV = this.scrollY;
66
+ this.scrollH = this.scrollX;
67
+
68
+ this.scrollableV = this.scrollableY;
69
+ this.scrollableH = this.scrollableX;
46
70
 
47
71
  this.rectForChild = function() { return this._rectForChild; };
48
72
  this.clientRect = function() { return this._clientRect; };
49
73
 
74
+ /**
75
+ * @function
76
+ * @param {Number} dx
77
+ * @param {Number} dy
78
+ * @name uki.view.ScrollPane#scroll
79
+ */
50
80
  this.scroll = function(dx, dy) {
51
- if (dx) this.scrollTop(this.scrollLeft() + dy);
81
+ if (dx) this.scrollLeft(this.scrollLeft() + dx);
52
82
  if (dy) this.scrollTop(this.scrollTop() + dy);
53
83
  };
54
84
 
85
+ /**
86
+ * @function
87
+ * @name uki.view.ScrollPane#scrollTop
88
+ */
89
+ /**
90
+ * @function
91
+ * @name uki.view.ScrollPane#scrollLeft
92
+ */
55
93
  uki.each(['scrollTop', 'scrollLeft'], function(i, name) {
56
94
  this[name] = function(v) {
57
95
  if (v == undefined) return this._dom[name];
@@ -61,6 +99,11 @@
61
99
  };
62
100
  }, this);
63
101
 
102
+ /**
103
+ * @function
104
+ * @return {uki.geometry.Rect}
105
+ * @name uki.view.ScrollPane#visibleRect
106
+ */
64
107
  this.visibleRect = function() {
65
108
  var tmpRect = this._clientRect.clone();
66
109
  tmpRect.x = this.rect().x + this.scrollLeft();
@@ -91,15 +134,15 @@
91
134
 
92
135
  var cw = this.contentsWidth(),
93
136
  ch = this.contentsHeight(),
94
- sh = this._scrollableH ? cw > this._rect.width : false,
95
- sv = this._scrollableV ? ch > this._rect.height : false;
137
+ sx = this._scrollableX ? cw > this._rect.width : false,
138
+ sy = this._scrollableY ? ch > this._rect.height : false;
96
139
 
97
- this._sbH = sh || this._scrollH;
98
- this._sbV = sv || this._scrollV;
99
- this._clientRect = new Rect( this._rect.width + (sv ? -1 : 0) * scrollWidth,
100
- this._rect.height + (sh ? -1 : 0) * scrollWidth );
101
- this._rectForChild = new Rect( this._rect.width + (sv && !widthIncludesScrollBar ? -1 : 0) * scrollWidth,
102
- this._rect.height + (sh && !widthIncludesScrollBar ? -1 : 0) * scrollWidth );
140
+ this._sbX = sx || this._scrollX;
141
+ this._sbY = sy || this._scrollY;
142
+ this._clientRect = new Rect( this._rect.width + (sy ? -1 : 0) * scrollWidth,
143
+ this._rect.height + (sx ? -1 : 0) * scrollWidth );
144
+ this._rectForChild = new Rect( this._rect.width + ((sy && !widthIncludesScrollBar) ? -1 : 0) * scrollWidth,
145
+ this._rect.height + ((sx && !widthIncludesScrollBar) ? -1 : 0) * scrollWidth );
103
146
  };
104
147
 
105
148
  this._updateClientRects = function() {
@@ -128,19 +171,34 @@
128
171
  this._layoutDom = function(rect) {
129
172
  this._updateClientRects();
130
173
 
131
- if (this._layoutScrollH !== this._sbH) {
132
- this._dom.style.overflowX = this._sbH ? 'scroll' : 'hidden';
133
- this._layoutScrollH = this._sbH;
174
+ if (this._layoutScrollX !== this._sbX) {
175
+ this._dom.style.overflowX = this._sbX ? 'scroll' : 'hidden';
176
+ this._layoutScrollX = this._sbX;
134
177
  }
135
178
 
136
- if (this._layoutScrollV !== this._sbV) {
137
- this._dom.style.overflowY = this._sbV ? 'scroll' : 'hidden';
138
- this._layoutScrollV = this._sbV;
179
+ if (this._layoutScrollY !== this._sbY) {
180
+ this._dom.style.overflowY = this._sbY ? 'scroll' : 'hidden';
181
+ this._layoutScrollY = this._sbY;
139
182
  }
140
183
 
141
184
  Base._layoutDom.call(this, rect);
142
185
  };
186
+
187
+ this.childResized = function() {
188
+ this._needsLayout = true;
189
+ uki.after(uki.proxy(this.layoutIfNeeded, this));
190
+ };
191
+
192
+ this._contentChanged = this.childResized;
193
+
143
194
  });
144
195
 
145
196
  uki.view.ScrollPane.initScrollWidth = initScrollWidth;
146
197
  })();
198
+
199
+ uki.Collection.addAttrs(['scrollTop', 'scrollLeft']);
200
+ uki.fn.scroll = function(dx, dy) {
201
+ this.each(function() {
202
+ this.scroll(dx, dy);
203
+ });
204
+ };
@@ -1,4 +1,15 @@
1
- uki.view.declare('uki.view.Slider', uki.view.Base, uki.view.Focusable, function(Base, Focusable) {
1
+ /**
2
+ * Horizontal Slider.
3
+ *
4
+ * @author voloko
5
+ * @name uki.view.Slider
6
+ * @class
7
+ * @extends uki.view.Base
8
+ * @implements uki.view.Focusable
9
+ */
10
+ uki.view.declare('uki.view.Slider', uki.view.Container, uki.view.Focusable, function(Base, Focusable) {
11
+
12
+ this._handleSize = new Size(10,18);
2
13
 
3
14
  this._setup = function() {
4
15
  Base._setup.call(this);
@@ -11,6 +22,22 @@ uki.view.declare('uki.view.Slider', uki.view.Base, uki.view.Focusable, function(
11
22
  });
12
23
  };
13
24
 
25
+ /**
26
+ * @function
27
+ * @name uki.view.Slider#min
28
+ */
29
+ /**
30
+ * @function
31
+ * @name uki.view.Slider#max
32
+ */
33
+ /**
34
+ * @function
35
+ * @name uki.view.Slider#values
36
+ */
37
+ /**
38
+ * @function
39
+ * @name uki.view.Slider#keyStep
40
+ */
14
41
  uki.addProps(this, ['min', 'max', 'values', 'keyStep']);
15
42
 
16
43
  this.values = uki.newProp('_values', function(val) {
@@ -20,74 +47,69 @@ uki.view.declare('uki.view.Slider', uki.view.Base, uki.view.Focusable, function(
20
47
  });
21
48
 
22
49
  /**
23
- * @fires event:change
24
- */
50
+ * @function
51
+ * @fires event:change
52
+ * @name uki.view.Slider#value
53
+ */
25
54
  this.value = uki.newProp('_value', function(val) {
26
55
  this._value = MAX(this._min, MIN(this._max, val));
27
56
  this._position = this._val2pos(this._value);
28
57
  this._moveHandle();
29
- this.trigger('change', {source: this, value: this._value});
30
58
  });
31
59
 
32
60
  this._pos2val = function(pos, cacheIndex) {
33
61
  if (this._values) {
34
- var index = Math.round(1.0 * pos / this._rect.width * (this._values.length - 1));
62
+ var index = Math.round(1.0 * pos / (this._rect.width - this._handleSize.width) * (this._values.length - 1));
35
63
  if (cacheIndex) this._cachedIndex = index;
36
64
  return this._values[index];
37
65
  }
38
- return pos / this._rect.width * (this._max - this._min);
66
+ return pos / (this._rect.width - this._handleSize.width) * (this._max - this._min) + this._min;
39
67
  };
40
68
 
41
69
  this._val2pos = function(val) {
42
70
  if (this._values) {
43
71
  var index = this._cachedIndex !== undefined ? this._cachedIndex : uki.binarySearch(val, this._values);
44
- return index / (this._values.length - 1) * this._rect.width;
72
+ return index / (this._values.length - 1) * (this._rect.width - this._handleSize.width);
45
73
  }
46
- return val / (this._max - this._min) * this._rect.width;
74
+ return (val - this._min) / (this._max - this._min) * (this._rect.width - this._handleSize.width);
47
75
  };
48
76
 
49
77
  this._createDom = function() {
50
78
  this._dom = uki.createElement('div', this.defaultCss + 'height:18px;-moz-user-select:none;-webkit-user-select:none;overflow:visible;');
51
- this._handle = uki.createElement('div', this.defaultCss + 'overflow:hidden;cursor:default;background:url(' + uki.theme.image('x').src + ')');
52
- this._bg = uki.theme.image('slider-handle');
53
- this._focusBg = uki.theme.image('slider-focus');
54
- this._focusBg.style.cssText += this._bg.style.cssText += this.defaultCss + 'top:0;left:0;z-index:-1;position:absolute;';
55
- this._handle.appendChild(this._bg);
56
-
79
+ this._initClassName();
80
+ this._handle = uki({
81
+ view: 'SliderHandle',
82
+ rect: new Rect(0, (this._rect.height-this._handleSize.height)/2, this._handleSize.width, this._handleSize.height),
83
+ anchors: 'left top'
84
+ })[0];
85
+ this.appendChild(this._handle);
57
86
 
58
87
  uki.theme.background('slider-bar').attachTo(this);
59
- this._initFocusable();
60
-
61
- uki.image.load([this._bg, this._focusBg], uki.proxy(this._afterHandleLoad, this) );
62
- };
63
-
64
- this._afterHandleLoad = function() {
65
- this._focusBg.style.cssText += ';z-index:10;margin-left:-' + (this._focusBg.width) / 2 + 'px;margin-top:-' + (this._focusBg.height-(this._bg.height/2)+1)/2 + 'px;';
66
- this._handle.style.cssText += ';margin-left:-' + (this._bg.width / 2) + 'px;width:' +this._bg.width + 'px;height:' + (this._bg.height / 2) + 'px;';
67
- this._dom.appendChild(this._handle);
68
-
69
- uki.each(['mouseenter', 'mouseleave', 'draggesturestart', 'draggesture', 'draggestureend'], function(i, name) {
70
- uki.dom.bind(this._handle, name, uki.proxy(this['_' + name], this));
88
+ uki.each(['draggesturestart', 'draggesture', 'draggestureend'], function(i, name) {
89
+ this._handle.bind(name, uki.proxy(this['_' + name], this));
71
90
  }, this);
72
91
 
73
- this.bind('click', this._click);
74
92
  this.bind(uki.view.List.prototype.keyPressEvent(), this._keypress);
93
+ this.bind('click', this._click);
94
+
95
+ this._initFocusable();
75
96
  };
76
97
 
77
- this._mouseenter = function() {
78
- this._over = true;
79
- this._bg.style.top = - this._bg.height / 2 + 'px';
98
+ this._focus = function(e) {
99
+ this._handle._focus();
100
+ Focusable._focus.call(this, e);
80
101
  };
81
-
82
- this._mouseleave = function() {
83
- this._over = false;
84
- this._bg.style.top = this._dragging ? (- this._bg.height / 2 + 'px') : 0;
102
+
103
+ this._blur = function(e) {
104
+ this._handle._blur();
105
+ Focusable._blur.call(this, e);
85
106
  };
86
107
 
87
108
  this._click = function(e) {
88
- var x = e.pageX - uki.dom.offset(this._dom).x;
109
+ var x = e.pageX - uki.dom.offset(this._dom).x - this._handleSize.width/2;
89
110
  this.value(this._pos2val(x, true));
90
111
  this._cachedIndex = undefined;
112
+ this.trigger('change', {source: this, value: this._value});
91
113
  };
92
114
 
93
115
  this._keypress = function(e) {
@@ -99,13 +121,15 @@ uki.view.declare('uki.view.Slider', uki.view.Base, uki.view.Focusable, function(
99
121
  };
100
122
 
101
123
  this._moveHandle = function() {
102
- // this._focusBg.style.left = this._handle.style.left = 100.0*this._position/this._rect.width + '%';
103
- this._focusBg.style.left = this._handle.style.left = this._position + 'px';
124
+ var rect = this._handle.rect().clone();
125
+ rect.x = this._position;
126
+ rect.y = (this._rect.height - this._handleSize.height) / 2;
127
+ this._handle.rect(rect).layout();
104
128
  };
105
129
 
106
130
  this._draggesturestart = function(e) {
107
131
  this._dragging = true;
108
- this._initialPosition = new Point(parseInt(this._handle.style.left, 10), parseInt(this._handle.style.top, 10));
132
+ this._initialPosition = this._handle.rect().clone();
109
133
  return true;
110
134
  };
111
135
 
@@ -113,7 +137,7 @@ uki.view.declare('uki.view.Slider', uki.view.Base, uki.view.Focusable, function(
113
137
  * @fires event:change
114
138
  */
115
139
  this._draggesture = function(e) {
116
- var position = MAX(0, MIN(this._rect.width, this._initialPosition.x + e.dragOffset.x));
140
+ var position = MAX(0, MIN(this._rect.width - this._handleSize.width, this._initialPosition.x + e.dragOffset.x));
117
141
  this.value(this._pos2val(position, true));
118
142
  this._cachedIndex = undefined;
119
143
  };
@@ -121,26 +145,13 @@ uki.view.declare('uki.view.Slider', uki.view.Base, uki.view.Focusable, function(
121
145
  this._draggestureend = function(e) {
122
146
  this._dragging = false;
123
147
  this._initialPosition = null;
124
- if (!this._over) this._bg.style.top = 0;
125
148
  this.value(this._pos2val(this._position, true));
126
149
  this._cachedIndex = undefined;
127
- };
128
-
129
- this._focus = function(e) {
130
- this._dom.appendChild(this._focusBg);
131
- this._focusBg.style.left = this._handle.style.left;
132
- Focusable._focus.call(this, e);
133
- };
134
-
135
- this._blur = function(e) {
136
- this._dom.removeChild(this._focusBg);
137
- Focusable._blur.call(this, e);
150
+ this.trigger('change', {source: this, value: this._value});
138
151
  };
139
152
 
140
153
  this._layoutDom = function(rect) {
141
- var fixedRect = rect.clone();
142
- fixedRect.height = 18;
143
- Base._layoutDom.call(this, fixedRect);
154
+ Base._layoutDom.call(this, rect);
144
155
  this._position = this._val2pos(this._value);
145
156
  this._moveHandle();
146
157
  return true;
@@ -152,3 +163,5 @@ uki.view.declare('uki.view.Slider', uki.view.Base, uki.view.Focusable, function(
152
163
  };
153
164
 
154
165
  });
166
+
167
+ uki.view.declare('uki.view.SliderHandle', uki.view.Button, { _backgroundPrefix: 'slider-handle-', _focusable: false });