uki 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (235) hide show
  1. data/.gitignore +7 -0
  2. data/.gitmodules +3 -0
  3. data/LICENSE +20 -0
  4. data/Rakefile +23 -0
  5. data/Readme.rdoc +9 -0
  6. data/VERSION +1 -0
  7. data/bin/uki +102 -0
  8. data/frameworks/jspec/lib/images/bg.png +0 -0
  9. data/frameworks/jspec/lib/images/hr.png +0 -0
  10. data/frameworks/jspec/lib/images/loading.gif +0 -0
  11. data/frameworks/jspec/lib/images/sprites.bg.png +0 -0
  12. data/frameworks/jspec/lib/images/sprites.png +0 -0
  13. data/frameworks/jspec/lib/images/vr.png +0 -0
  14. data/frameworks/jspec/lib/jspec.css +149 -0
  15. data/frameworks/jspec/lib/jspec.growl.js +115 -0
  16. data/frameworks/jspec/lib/jspec.jquery.js +72 -0
  17. data/frameworks/jspec/lib/jspec.js +1756 -0
  18. data/frameworks/jspec/lib/jspec.shell.js +39 -0
  19. data/frameworks/jspec/lib/jspec.timers.js +90 -0
  20. data/frameworks/jspec/lib/jspec.xhr.js +195 -0
  21. data/frameworks/uki/README.rdoc +179 -0
  22. data/frameworks/uki/compiler.jar +0 -0
  23. data/frameworks/uki/run.rb +2 -0
  24. data/frameworks/uki/spec/commands/example_command.rb +19 -0
  25. data/frameworks/uki/spec/dom.html +39 -0
  26. data/frameworks/uki/spec/support/images/bg.png +0 -0
  27. data/frameworks/uki/spec/support/images/hr.png +0 -0
  28. data/frameworks/uki/spec/support/images/loading.gif +0 -0
  29. data/frameworks/uki/spec/support/images/sprites.bg.png +0 -0
  30. data/frameworks/uki/spec/support/images/sprites.png +0 -0
  31. data/frameworks/uki/spec/support/images/vr.png +0 -0
  32. data/frameworks/uki/spec/support/jspec.css +149 -0
  33. data/frameworks/uki/spec/support/jspec.js +1773 -0
  34. data/frameworks/uki/spec/support/jspec.xhr.js +193 -0
  35. data/frameworks/uki/spec/support/spec.helper.js +1 -0
  36. data/frameworks/uki/spec/unit/background.spec.js +29 -0
  37. data/frameworks/uki/spec/unit/builder.spec.js +51 -0
  38. data/frameworks/uki/spec/unit/data/model.spec.js +29 -0
  39. data/frameworks/uki/spec/unit/dom/dnd.spec.js +71 -0
  40. data/frameworks/uki/spec/unit/dom/event.spec.js +78 -0
  41. data/frameworks/uki/spec/unit/dom.spec.js +28 -0
  42. data/frameworks/uki/spec/unit/geometry.spec.js +79 -0
  43. data/frameworks/uki/spec/unit/selector.spec.js +140 -0
  44. data/frameworks/uki/spec/unit/theme/template.spec.js +31 -0
  45. data/frameworks/uki/spec/unit/utils.spec.js +176 -0
  46. data/frameworks/uki/spec/unit/view/base.spec.js +86 -0
  47. data/frameworks/uki/spec/unit/view/container.spec.js +73 -0
  48. data/frameworks/uki/spec/unit/view.spec.js +13 -0
  49. data/frameworks/uki/src/airport.js +1 -0
  50. data/frameworks/uki/src/uki-core/attachment.js +175 -0
  51. data/frameworks/uki/src/uki-core/background/css.js +37 -0
  52. data/frameworks/uki/src/uki-core/background/cssBox.js +73 -0
  53. data/frameworks/uki/src/uki-core/background/multi.js +20 -0
  54. data/frameworks/uki/src/uki-core/background/null.js +10 -0
  55. data/frameworks/uki/src/uki-core/background/rows.js +77 -0
  56. data/frameworks/uki/src/uki-core/background/sliced9.js +206 -0
  57. data/frameworks/uki/src/uki-core/background.js +35 -0
  58. data/frameworks/uki/src/uki-core/builder.js +68 -0
  59. data/frameworks/uki/src/uki-core/collection.js +278 -0
  60. data/frameworks/uki/src/uki-core/const.js +17 -0
  61. data/frameworks/uki/src/uki-core/dom/dnd.js +93 -0
  62. data/frameworks/uki/src/uki-core/dom/event.js +194 -0
  63. data/frameworks/uki/src/uki-core/dom/nativeLayout.js +18 -0
  64. data/frameworks/uki/src/uki-core/dom/offset.js +130 -0
  65. data/frameworks/uki/src/uki-core/dom/w3cdnd.js +333 -0
  66. data/frameworks/uki/src/uki-core/dom.js +109 -0
  67. data/frameworks/uki/src/uki-core/geometry.js +658 -0
  68. data/frameworks/uki/src/uki-core/image.js +90 -0
  69. data/frameworks/uki/src/uki-core/selector.js +201 -0
  70. data/frameworks/uki/src/uki-core/theme/base.js +39 -0
  71. data/frameworks/uki/src/uki-core/theme/template.js +26 -0
  72. data/frameworks/uki/src/uki-core/theme.js +45 -0
  73. data/frameworks/uki/src/uki-core/uki.js +45 -0
  74. data/frameworks/uki/src/uki-core/utils.js +399 -0
  75. data/frameworks/uki/src/uki-core/view/base.js +480 -0
  76. data/frameworks/uki/src/uki-core/view/container.js +155 -0
  77. data/frameworks/uki/src/uki-core/view/focusable.js +93 -0
  78. data/frameworks/uki/src/uki-core/view/observable.js +66 -0
  79. data/frameworks/uki/src/uki-core/view/styleable.js +70 -0
  80. data/frameworks/uki/src/uki-core/view/utils.js +66 -0
  81. data/frameworks/uki/src/uki-core/view.js +21 -0
  82. data/frameworks/uki/src/uki-core.js +36 -0
  83. data/frameworks/uki/src/uki-data/data.js +1 -0
  84. data/frameworks/uki/src/uki-data/model.js +28 -0
  85. data/frameworks/uki/src/uki-data/observable.js +34 -0
  86. data/frameworks/uki/src/uki-data.js +1 -0
  87. data/frameworks/uki/src/uki-more/more/utils.js +20 -0
  88. data/frameworks/uki/src/uki-more/more/view/listContainer.js +4 -0
  89. data/frameworks/uki/src/uki-more/more/view/multiselectList.js +196 -0
  90. data/frameworks/uki/src/uki-more/more/view/radioButton.js +27 -0
  91. data/frameworks/uki/src/uki-more/more/view/splitTable.js +79 -0
  92. data/frameworks/uki/src/uki-more/more/view/toggleButton.js +24 -0
  93. data/frameworks/uki/src/uki-more/more/view/treeList/render.js +53 -0
  94. data/frameworks/uki/src/uki-more/more/view/treeList.js +110 -0
  95. data/frameworks/uki/src/uki-more/more/view.js +2 -0
  96. data/frameworks/uki/src/uki-more/more.js +1 -0
  97. data/frameworks/uki/src/uki-more.js +4 -0
  98. data/frameworks/uki/src/uki-theamless.js +15 -0
  99. data/frameworks/uki/src/uki-theme/airport/i/button/down-c.gif +0 -0
  100. data/frameworks/uki/src/uki-theme/airport/i/button/down-c.png +0 -0
  101. data/frameworks/uki/src/uki-theme/airport/i/button/down-h.gif +0 -0
  102. data/frameworks/uki/src/uki-theme/airport/i/button/down-h.png +0 -0
  103. data/frameworks/uki/src/uki-theme/airport/i/button/down-m.png +0 -0
  104. data/frameworks/uki/src/uki-theme/airport/i/button/down-v.png +0 -0
  105. data/frameworks/uki/src/uki-theme/airport/i/button/focusRing-c.png +0 -0
  106. data/frameworks/uki/src/uki-theme/airport/i/button/focusRing-h.png +0 -0
  107. data/frameworks/uki/src/uki-theme/airport/i/button/focusRing-m.png +0 -0
  108. data/frameworks/uki/src/uki-theme/airport/i/button/focusRing-v.png +0 -0
  109. data/frameworks/uki/src/uki-theme/airport/i/button/focusRing.png +0 -0
  110. data/frameworks/uki/src/uki-theme/airport/i/button/hover-c.gif +0 -0
  111. data/frameworks/uki/src/uki-theme/airport/i/button/hover-c.png +0 -0
  112. data/frameworks/uki/src/uki-theme/airport/i/button/hover-h.gif +0 -0
  113. data/frameworks/uki/src/uki-theme/airport/i/button/hover-h.png +0 -0
  114. data/frameworks/uki/src/uki-theme/airport/i/button/hover-m.png +0 -0
  115. data/frameworks/uki/src/uki-theme/airport/i/button/hover-v.png +0 -0
  116. data/frameworks/uki/src/uki-theme/airport/i/button/hover.png +0 -0
  117. data/frameworks/uki/src/uki-theme/airport/i/button/normal-c.gif +0 -0
  118. data/frameworks/uki/src/uki-theme/airport/i/button/normal-c.png +0 -0
  119. data/frameworks/uki/src/uki-theme/airport/i/button/normal-h.gif +0 -0
  120. data/frameworks/uki/src/uki-theme/airport/i/button/normal-h.png +0 -0
  121. data/frameworks/uki/src/uki-theme/airport/i/button/normal-m.png +0 -0
  122. data/frameworks/uki/src/uki-theme/airport/i/button/normal-v.png +0 -0
  123. data/frameworks/uki/src/uki-theme/airport/i/button/normal.png +0 -0
  124. data/frameworks/uki/src/uki-theme/airport/i/checkbox/checkbox.png +0 -0
  125. data/frameworks/uki/src/uki-theme/airport/i/checkbox/focus.png +0 -0
  126. data/frameworks/uki/src/uki-theme/airport/i/checkbox/normal.gif +0 -0
  127. data/frameworks/uki/src/uki-theme/airport/i/checkbox/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/radio/focus.png +0 -0
  134. data/frameworks/uki/src/uki-theme/airport/i/radio/normal.gif +0 -0
  135. data/frameworks/uki/src/uki-theme/airport/i/radio/normal.png +0 -0
  136. data/frameworks/uki/src/uki-theme/airport/i/radio/radio.png +0 -0
  137. data/frameworks/uki/src/uki-theme/airport/i/shadow/large-c.png +0 -0
  138. data/frameworks/uki/src/uki-theme/airport/i/shadow/large-h.png +0 -0
  139. data/frameworks/uki/src/uki-theme/airport/i/shadow/large-m.png +0 -0
  140. data/frameworks/uki/src/uki-theme/airport/i/shadow/large-v.png +0 -0
  141. data/frameworks/uki/src/uki-theme/airport/i/shadow/large.png +0 -0
  142. data/frameworks/uki/src/uki-theme/airport/i/slider/bar-m.gif +0 -0
  143. data/frameworks/uki/src/uki-theme/airport/i/slider/bar-m.png +0 -0
  144. data/frameworks/uki/src/uki-theme/airport/i/slider/bar-v.gif +0 -0
  145. data/frameworks/uki/src/uki-theme/airport/i/slider/bar-v.png +0 -0
  146. data/frameworks/uki/src/uki-theme/airport/i/slider/bar.png +0 -0
  147. data/frameworks/uki/src/uki-theme/airport/i/slider/focus.png +0 -0
  148. data/frameworks/uki/src/uki-theme/airport/i/slider/handle.gif +0 -0
  149. data/frameworks/uki/src/uki-theme/airport/i/splitPane/horizontal.gif +0 -0
  150. data/frameworks/uki/src/uki-theme/airport/i/splitPane/horizontal.png +0 -0
  151. data/frameworks/uki/src/uki-theme/airport/i/splitPane/vertical.gif +0 -0
  152. data/frameworks/uki/src/uki-theme/airport/i/x.gif +0 -0
  153. data/frameworks/uki/src/uki-theme/airport.js +322 -0
  154. data/frameworks/uki/src/uki-theme/aristo/i/button/down-c.gif +0 -0
  155. data/frameworks/uki/src/uki-theme/aristo/i/button/down-c.png +0 -0
  156. data/frameworks/uki/src/uki-theme/aristo/i/button/down-h.png +0 -0
  157. data/frameworks/uki/src/uki-theme/aristo/i/button/down-m.png +0 -0
  158. data/frameworks/uki/src/uki-theme/aristo/i/button/down-v.png +0 -0
  159. data/frameworks/uki/src/uki-theme/aristo/i/button/down.png +0 -0
  160. data/frameworks/uki/src/uki-theme/aristo/i/button/focusRing-c.png +0 -0
  161. data/frameworks/uki/src/uki-theme/aristo/i/button/focusRing-h.png +0 -0
  162. data/frameworks/uki/src/uki-theme/aristo/i/button/focusRing-m.png +0 -0
  163. data/frameworks/uki/src/uki-theme/aristo/i/button/focusRing-v.png +0 -0
  164. data/frameworks/uki/src/uki-theme/aristo/i/button/focusRing.png +0 -0
  165. data/frameworks/uki/src/uki-theme/aristo/i/button/normal-c.gif +0 -0
  166. data/frameworks/uki/src/uki-theme/aristo/i/button/normal-c.png +0 -0
  167. data/frameworks/uki/src/uki-theme/aristo/i/button/normal-h.png +0 -0
  168. data/frameworks/uki/src/uki-theme/aristo/i/button/normal-m.png +0 -0
  169. data/frameworks/uki/src/uki-theme/aristo/i/button/normal-v.png +0 -0
  170. data/frameworks/uki/src/uki-theme/aristo/i/button/normal.png +0 -0
  171. data/frameworks/uki/src/uki-theme/aristo/i/checkbox/focus.png +0 -0
  172. data/frameworks/uki/src/uki-theme/aristo/i/checkbox/normal.gif +0 -0
  173. data/frameworks/uki/src/uki-theme/aristo/i/checkbox/normal.png +0 -0
  174. data/frameworks/uki/src/uki-theme/aristo/i/panel/normal-h.png +0 -0
  175. data/frameworks/uki/src/uki-theme/aristo/i/panel/normal-m.png +0 -0
  176. data/frameworks/uki/src/uki-theme/aristo/i/panel/normal.png +0 -0
  177. data/frameworks/uki/src/uki-theme/aristo/i/popup/normal.png +0 -0
  178. data/frameworks/uki/src/uki-theme/aristo/i/radio/focus.png +0 -0
  179. data/frameworks/uki/src/uki-theme/aristo/i/radio/normal.gif +0 -0
  180. data/frameworks/uki/src/uki-theme/aristo/i/radio/normal.png +0 -0
  181. data/frameworks/uki/src/uki-theme/aristo/i/shadow/large-c.png +0 -0
  182. data/frameworks/uki/src/uki-theme/aristo/i/shadow/large-h.png +0 -0
  183. data/frameworks/uki/src/uki-theme/aristo/i/shadow/large-m.png +0 -0
  184. data/frameworks/uki/src/uki-theme/aristo/i/shadow/large-v.png +0 -0
  185. data/frameworks/uki/src/uki-theme/aristo/i/shadow/large.png +0 -0
  186. data/frameworks/uki/src/uki-theme/aristo/i/slider/bar-m.gif +0 -0
  187. data/frameworks/uki/src/uki-theme/aristo/i/slider/bar-m.png +0 -0
  188. data/frameworks/uki/src/uki-theme/aristo/i/slider/bar-v.gif +0 -0
  189. data/frameworks/uki/src/uki-theme/aristo/i/slider/bar-v.png +0 -0
  190. data/frameworks/uki/src/uki-theme/aristo/i/slider/bar.png +0 -0
  191. data/frameworks/uki/src/uki-theme/aristo/i/slider/handle.gif +0 -0
  192. data/frameworks/uki/src/uki-theme/aristo/i/slider/handle.png +0 -0
  193. data/frameworks/uki/src/uki-theme/aristo/i/splitPane/horizontal.gif +0 -0
  194. data/frameworks/uki/src/uki-theme/aristo/i/splitPane/horizontal.png +0 -0
  195. data/frameworks/uki/src/uki-theme/aristo/i/splitPane/vertical.gif +0 -0
  196. data/frameworks/uki/src/uki-theme/aristo/i/x.gif +0 -0
  197. data/frameworks/uki/src/uki-theme/aristo.js +217 -0
  198. data/frameworks/uki/src/uki-view/view/box.js +1 -0
  199. data/frameworks/uki/src/uki-view/view/button.js +126 -0
  200. data/frameworks/uki/src/uki-view/view/checkbox.js +36 -0
  201. data/frameworks/uki/src/uki-view/view/flow.js +48 -0
  202. data/frameworks/uki/src/uki-view/view/image.js +9 -0
  203. data/frameworks/uki/src/uki-view/view/label.js +123 -0
  204. data/frameworks/uki/src/uki-view/view/list/render.js +23 -0
  205. data/frameworks/uki/src/uki-view/view/list.js +442 -0
  206. data/frameworks/uki/src/uki-view/view/popup.js +113 -0
  207. data/frameworks/uki/src/uki-view/view/radio.js +57 -0
  208. data/frameworks/uki/src/uki-view/view/scrollPane.js +139 -0
  209. data/frameworks/uki/src/uki-view/view/slider.js +154 -0
  210. data/frameworks/uki/src/uki-view/view/splitPane.js +213 -0
  211. data/frameworks/uki/src/uki-view/view/table/column.js +96 -0
  212. data/frameworks/uki/src/uki-view/view/table/header.js +53 -0
  213. data/frameworks/uki/src/uki-view/view/table/render.js +25 -0
  214. data/frameworks/uki/src/uki-view/view/table.js +71 -0
  215. data/frameworks/uki/src/uki-view/view/textField.js +145 -0
  216. data/frameworks/uki/src/uki-view/view/toolbar.js +93 -0
  217. data/frameworks/uki/src/uki-view.js +15 -0
  218. data/frameworks/uki/src/uki.js +2 -0
  219. data/frameworks/uki/thin.yaml +11 -0
  220. data/frameworks/uki/uki.rb +38 -0
  221. data/frameworks/uki/uki.ru +2 -0
  222. data/lib/uki/include_js.rb +50 -0
  223. data/lib/uki/project.rb +207 -0
  224. data/lib/uki/routes.rb +20 -0
  225. data/lib/uki/server.rb +42 -0
  226. data/lib/uki.rb +9 -0
  227. data/templates/index.html.erb +10 -0
  228. data/templates/model.js.erb +5 -0
  229. data/templates/myapp.js.erb +44 -0
  230. data/templates/package.js.erb +3 -0
  231. data/templates/spec.html.erb +23 -0
  232. data/templates/spec.js.erb +6 -0
  233. data/templates/view.js.erb +10 -0
  234. data/uki.gemspec +281 -0
  235. metadata +317 -0
@@ -0,0 +1,93 @@
1
+ include('../view.js');
2
+ include('observable.js');
3
+
4
+ /**
5
+ * @class
6
+ */
7
+ uki.view.Focusable = /** @lends uki.view.Focusable.prototype */ {
8
+ // dom: function() {
9
+ // return null; // should implement
10
+ // },
11
+ _focusable: true, // default value
12
+
13
+ focusable: uki.newProp('_focusable', function(v) {
14
+ this._focusable = v;
15
+ this._updateTabIndex();
16
+ }),
17
+
18
+ disabled: uki.newProp('_disabled', function(d) {
19
+ this._disabled = d;
20
+ if (d) this.blur();
21
+ this._updateTabIndex();
22
+ if (this._updateBg) this._updateBg();
23
+ }),
24
+
25
+ _updateTabIndex: function() {
26
+ if (this._focusTarget) {
27
+ if (this._focusable && !this._disabled) this._focusTarget.setAttribute('tabIndex', 1)
28
+ else this._focusTarget.removeAttribute('tabIndex');
29
+ }
30
+ },
31
+
32
+ _initFocusable: function(preCreatedInput) {
33
+ this._focusTarget = preCreatedInput;
34
+
35
+ if (!preCreatedInput) {
36
+ this._focusTarget = root.opera ? uki.createElement('div', 'position:absolute;left:-999px;top:0;width:1px;height:1px;') : this.dom();
37
+ if (root.opera) this.dom().appendChild(this._focusTarget);
38
+ this._updateTabIndex();
39
+ this._focusTarget.style.outline = 'none';
40
+ this._focusTarget.hideFocus = true;
41
+ }
42
+ this._hasFocus = false;
43
+ this._firstFocus = true;
44
+
45
+ uki.dom.bind(this._focusTarget, 'focus', uki.proxy(function(e) {
46
+ if (!this._hasFocus) this._focus(e);
47
+ }, this));
48
+ uki.dom.bind(this._focusTarget, 'blur', uki.proxy(function(e) {
49
+ if (this._hasFocus) this._blur(e);
50
+ }, this));
51
+
52
+ if (!preCreatedInput) this.bind('mousedown', function(e) {
53
+ setTimeout(uki.proxy(function() {
54
+ try { this.focus(); } catch (e) {};
55
+ }, this), 1);
56
+ });
57
+ },
58
+
59
+ _focus: function(e) {
60
+ this._hasFocus = true;
61
+ this._firstFocus = false;
62
+ },
63
+
64
+ _blur: function(e) {
65
+ this._hasFocus = false;
66
+ },
67
+
68
+ focus: function() {
69
+ try {
70
+ if (this._focusable && !this._disabled) this._focusTarget.focus();
71
+ } catch(e) {}
72
+ return this;
73
+ },
74
+
75
+ blur: function() {
76
+ try {
77
+ this._focusTarget.blur();
78
+ } catch(e) {}
79
+ return this;
80
+ },
81
+
82
+ hasFocus: function() {
83
+ return this._hasFocus;
84
+ },
85
+
86
+ _bindToDom: function(name) {
87
+ if (!this._focusTarget || 'keyup keydown keypress focus blur'.indexOf(name) == -1) return false;
88
+
89
+ return uki.view.Observable._bindToDom.call(this, name, this._focusableInput);
90
+ }
91
+
92
+
93
+ };
@@ -0,0 +1,66 @@
1
+ include('../view.js');
2
+
3
+ /**
4
+ * @class
5
+ */
6
+ uki.view.Observable = /** @lends uki.view.Observable.prototype */ {
7
+ // dom: function() {
8
+ // return null; // should implement
9
+ // },
10
+
11
+ bind: function(name, callback) {
12
+ uki.each(name.split(' '), function(i, name) {
13
+ if (!this._bound(name)) this._bindToDom(name);
14
+ this._observersFor(name).push(callback);
15
+ }, this);
16
+ return this;
17
+ },
18
+
19
+ unbind: function(name, callback) {
20
+ uki.each(name.split(' '), function(i, name) {
21
+ this._observers[name] = uki.grep(this._observers[name], function(observer) {
22
+ return observer != callback;
23
+ });
24
+ if (this._observers[name].length == 0) {
25
+ this._unbindFromDom(name);
26
+ }
27
+ }, this);
28
+ return this;
29
+ },
30
+
31
+ trigger: function(name/*, data1, data2*/) {
32
+ var attrs = Array.prototype.slice.call(arguments, 1);
33
+ uki.each(this._observersFor(name, true), function(i, callback) {
34
+ callback.apply(this, attrs);
35
+ }, this);
36
+ return this;
37
+ },
38
+
39
+ _unbindFromDom: function(name) {
40
+ if (!this._domHander || !this._eventTargets[name]) return;
41
+ uki.dom.unbind(this._eventTargets[name], name, this._domHander);
42
+ },
43
+
44
+ _bindToDom: function(name, target) {
45
+ if (!target && !this.dom) return;
46
+ this._domHander = this._domHander || uki.proxy(function(e) {
47
+ e.source = this;
48
+ this.trigger(e.type, e);
49
+ }, this);
50
+ this._eventTargets = this._eventTargets || {};
51
+ this._eventTargets[name] = target || this.dom();
52
+ uki.dom.bind(this._eventTargets[name], name, this._domHander);
53
+ return true;
54
+ },
55
+
56
+ _bound: function(name) {
57
+ return this._observers && this._observers[name];
58
+ },
59
+
60
+ _observersFor: function(name, skipCreate) {
61
+ if (skipCreate && (!this._observers || !this._observers[name])) return [];
62
+ if (!this._observers) this._observers = {};
63
+ if (!this._observers[name]) this._observers[name] = [];
64
+ return this._observers[name];
65
+ }
66
+ };
@@ -0,0 +1,70 @@
1
+ include('../view.js');
2
+
3
+ /**
4
+ * @class
5
+ */
6
+ uki.view.Styleable = new function() {
7
+ /** @scope uki.view.Styleable.prototype */
8
+
9
+ /**
10
+ * @name style
11
+ * @memberOf uki.view.Styleable#
12
+ * @function
13
+ */
14
+ this.style = function(name, value) {
15
+ if (typeof name == 'string') return this._style(name, value);
16
+
17
+ uki.each(name, function(name, value) {
18
+ this._style(name, value);
19
+ }, this);
20
+ return this;
21
+ };
22
+
23
+ this._style = function(name, value) {
24
+ if (value === undefined) return this._dom.style[name];
25
+ this._dom.style[name] = value;
26
+ return this;
27
+ };
28
+
29
+ // TODO: is this really needed?
30
+ // uki.each('fontSize,textAlign,color,fontFamily,fontWeight,lineHeight,zIndex'.split(','), function(i, name) {
31
+ // proto[name] = function(value) {
32
+ // return this._style(name, value);
33
+ // };
34
+ // });
35
+
36
+ var probe = uki.createElement('div').style,
37
+ proto = this;
38
+ uki.each(['userSelect', 'MozUserSelect', 'WebkitUserSelect'], function() {
39
+ if (typeof probe[this] == 'string') proto._textSelectProp = this;
40
+ });
41
+
42
+ /**
43
+ * Sets whether text of the view can be selected.
44
+ *
45
+ * @memberOf uki.view.Styleable#
46
+ * @name textSelectable
47
+ * @function
48
+ * @param {boolean=} state
49
+ * @returns {boolean|uki.view.Base} current textSelectable state of self
50
+ */
51
+ this.textSelectable = function(state) {
52
+ if (state === undefined) return this._textSelectable;
53
+ this._textSelectable = state;
54
+ if (this._textSelectProp) {
55
+ this._dom.style[this._textSelectProp] = state ? '' : this._textSelectProp == 'MozUserSelect' ? '-moz-none' : 'none';
56
+ } else {
57
+ // uki.dom[state ? 'unbind' : 'bind'](this.dom(), 'selectstart mousedown', uki.dom.preventDefaultHandler);
58
+ }
59
+ this._dom.style.cursor = state ? 'text' : 'default';
60
+ return this;
61
+ };
62
+
63
+ this.draggable = function(state) {
64
+ if (state === undefined) return this._dom.getAttribute('draggable');
65
+ this._dom.setAttribute('draggable', true);
66
+ this._dom.style.WebkitUserDrag = 'element';
67
+ };
68
+
69
+ /**#@-*/
70
+ };
@@ -0,0 +1,66 @@
1
+ include('../view.js');
2
+
3
+ /**
4
+ * @namespace
5
+ */
6
+ uki.view.utils = new function() {
7
+ this.visibleRect = function (from, upTo) {
8
+ var queue = [],
9
+ rect, i, tmpRect, c = from;
10
+
11
+ do {
12
+ queue[queue.length] = c;
13
+ c = c.parent();
14
+ } while (c && c != upTo);
15
+
16
+ if (upTo && upTo != from) queue[queue.length] = upTo;
17
+
18
+ for (i = queue.length - 1; i >= 0; i--){
19
+ c = queue[i];
20
+ tmpRect = visibleRect(c);
21
+ rect = rect ? rect.intersection(tmpRect) : tmpRect;
22
+ rect.x -= c.rect().x;
23
+ rect.y -= c.rect().y;
24
+
25
+ };
26
+ return rect;
27
+ };
28
+
29
+ this.top = function(c) {
30
+ while (c.parent()) c = c.parent();
31
+ return c;
32
+ };
33
+
34
+ this.offset = function(c, upTo) {
35
+ var offset = new Point(),
36
+ rect;
37
+
38
+ while (c && c != upTo) {
39
+ rect = c.rect();
40
+ offset.x += rect.x;
41
+ offset.y += rect.y;
42
+ if (c.scrollTop) {
43
+ offset.x -= c.scrollLeft();
44
+ offset.y -= c.scrollTop();
45
+ }
46
+ c = c.parent();
47
+ }
48
+ return offset;
49
+ };
50
+
51
+ this.scrollableParent = function(c) {
52
+ do {
53
+ if (uki.isFunction(c.scrollTop)) return c;
54
+ c = c.parent();
55
+ } while (c);
56
+ return null;
57
+ };
58
+
59
+ /** @inner */
60
+ function visibleRect (c) {
61
+ return c.visibleRect ? c.visibleRect() : c.rect().clone();
62
+ }
63
+ /**#@-*/
64
+ };
65
+
66
+ uki.extend(uki.view, uki.view.utils);
@@ -0,0 +1,21 @@
1
+ include('uki.js');
2
+ /** @namespace */
3
+ uki.view = {
4
+ declare: function(/*name, baseClasses, implementation*/) {
5
+ var args = uki.toArray(arguments),
6
+ name = args.shift(),
7
+ klass = uki.newClass.apply(uki, args),
8
+ parts = name.split('.'),
9
+ obj = root,
10
+ i, part;
11
+
12
+ klass.prototype.typeName = function() { return name; };
13
+ for ( i=0; i < parts.length - 1; i++ ) {
14
+ part = parts[i];
15
+ if (!obj[part]) obj[part] = {};
16
+ obj = obj[part];
17
+ };
18
+ obj[parts[parts.length - 1]] = klass;
19
+ return klass;
20
+ }
21
+ };
@@ -0,0 +1,36 @@
1
+ include('uki-core/const.js');
2
+ include('uki-core/uki.js');
3
+ include('uki-core/utils.js');
4
+ include('uki-core/geometry.js');
5
+
6
+ include('uki-core/dom.js');
7
+ include('uki-core/dom/event.js');
8
+ include('uki-core/dom/dnd.js');
9
+ include('uki-core/dom/w3cdnd.js');
10
+ include('uki-core/dom/offset.js');
11
+ include('uki-core/dom/nativeLayout.js');
12
+
13
+ include('uki-core/attachment.js');
14
+ include('uki-core/builder.js');
15
+ include('uki-core/selector.js');
16
+
17
+ include('uki-core/image.js');
18
+
19
+ include('uki-core/background.js');
20
+ include('uki-core/background/null.js');
21
+ include('uki-core/background/sliced9.js');
22
+ include('uki-core/background/css.js');
23
+ include('uki-core/background/cssBox.js');
24
+ include('uki-core/background/rows.js');
25
+ include('uki-core/background/multi.js');
26
+
27
+ include('uki-core/theme.js');
28
+ include('uki-core/theme/base.js');
29
+ include('uki-core/theme/template.js');
30
+
31
+ include('uki-core/view/utils.js');
32
+ include('uki-core/view/styleable.js');
33
+ include('uki-core/view/observable.js');
34
+ include('uki-core/view/focusable.js');
35
+ include('uki-core/view/base.js');
36
+ include('uki-core/view/container.js');
@@ -0,0 +1 @@
1
+ uki.data = {};
@@ -0,0 +1,28 @@
1
+ include('observable.js');
2
+
3
+ uki.data.Model = uki.newClass(uki.data.Observable, function(Observable) {
4
+
5
+ this.change = this.update = function(values, arg2) {
6
+ var changes = {}, fields = [];
7
+ if (arg2 !== undefined) {
8
+ var tmp = {};
9
+ tmp[values] = arg2;
10
+ values = tmp;
11
+ }
12
+ uki.each(values, function(i) {
13
+ if (this[i] != values[i]) {
14
+ changes[i] = true
15
+ fields.push(i);
16
+ this[i] = values[i];
17
+ }
18
+ }, this);
19
+
20
+ this._triggerChange({changes: changes, fields: fields, model: this});
21
+ return this;
22
+ };
23
+
24
+ this._triggerChange = function(e) {
25
+ this.trigger('change', e);
26
+ };
27
+
28
+ });
@@ -0,0 +1,34 @@
1
+ include('data.js');
2
+ /**
3
+ * Легковесная поддержка событий без баблинга
4
+ */
5
+ uki.data.Observable = {
6
+ bind: function(name, callback) {
7
+ var _this = this;
8
+ uki.each(name.split(' '), function(i, name) {
9
+ _this._observersFor(name).push(callback);
10
+ });
11
+ },
12
+
13
+ unbind: function(name, callback) {
14
+ var _this = this;
15
+ uki.each(name.split(' '), function(i, name) {
16
+ _this._observers[name] = uki.grep(_this._observersFor(name), function(c) {
17
+ return c != callback;
18
+ });
19
+ });
20
+ },
21
+
22
+ trigger: function(name/*, data1, data2*/) {
23
+ var attrs = Array.prototype.slice.call(arguments, 1);
24
+ uki.each(this._observersFor(name), function(i, callback) {
25
+ callback.apply(this, attrs);
26
+ });
27
+ },
28
+
29
+ _observersFor: function(name) {
30
+ if (!this._observers) this._observers = {};
31
+ if (!this._observers[name]) this._observers[name] = [];
32
+ return this._observers[name];
33
+ }
34
+ };
@@ -0,0 +1 @@
1
+ include('uki-data/model.js');
@@ -0,0 +1,20 @@
1
+ include('../more.js');
2
+
3
+ uki.more.utils = {
4
+ range: function (from, to) {
5
+ var result = new Array(to - from);
6
+ for (var idx = 0; from <= to; from++, idx++) {
7
+ result[idx] = from;
8
+ };
9
+ return result;
10
+ },
11
+
12
+ binarySearch: function (array, value) {
13
+ var low = 0, high = array.length, mid;
14
+ while (low < high) {
15
+ mid = (low + high) >> 1;
16
+ array[mid] < value ? low = mid + 1 : high = mid;
17
+ }
18
+ return low;
19
+ }
20
+ };
@@ -0,0 +1,4 @@
1
+ uki.more.view.ListContainer = uki.newClass(uki.view.Container, new function() {
2
+ var Base = uki.view.Container.prototype;
3
+
4
+ });
@@ -0,0 +1,196 @@
1
+ include('../view.js');
2
+ include('../utils.js');
3
+
4
+ uki.view.declare('uki.more.view.MultiselectList', uki.view.List, function(Base) {
5
+
6
+ this._setup = function() {
7
+ Base._setup.call(this);
8
+ uki.extend(this, {
9
+ _selectedIndexes: [],
10
+ _lastClickIndex: -1
11
+ });
12
+ };
13
+
14
+ this.lastClickIndex = uki.newProp('_lastClickIndex');
15
+
16
+ this.clearSelection = function(skipClickIndex) {
17
+ for (var i=0; i < this._selectedIndexes.length; i++) {
18
+ this._setSelected(this._selectedIndexes[i], false);
19
+ };
20
+ this._selectedIndexes = [];
21
+ if (!skipClickIndex) this._lastClickIndex = -1;
22
+ };
23
+
24
+ this.selectedIndexes = function(indexes) {
25
+ if (indexes === undefined) return this._selectedIndexes;
26
+ this.clearSelection(true);
27
+ this._selectedIndexes = indexes;
28
+ for (var i=0; i < this._selectedIndexes.length; i++) {
29
+ this._setSelected(this._selectedIndexes[i], true);
30
+ };
31
+ this.trigger('selection', {source: this});
32
+ return this;
33
+ };
34
+
35
+ this.selectedRows = function() {
36
+ return uki.map(this.selectedIndexes(), function(index) {
37
+ return this._data[index];
38
+ }, this)
39
+ };
40
+
41
+ this.selectedIndex = function(position) {
42
+ if (position === undefined) return this._selectedIndexes.length ? this._selectedIndexes[0] : -1;
43
+ this.selectedIndexes([position]);
44
+ this._scrollToPosition(position);
45
+ return this;
46
+ };
47
+
48
+ function removeRange (array, from, to) {
49
+ var p = uki.more.utils.binarySearch(array, from),
50
+ initialP = p;
51
+ while (array[p] <= to) p++;
52
+ if (p > initialP) array.splice(initialP, p - initialP);
53
+ }
54
+
55
+ this._toggleSelection = function(p) {
56
+ var indexes = [].concat(this._selectedIndexes);
57
+ var addTo = uki.more.utils.binarySearch(indexes, p);
58
+ if (indexes[addTo] == p) {
59
+ indexes.splice(addTo, 1);
60
+ } else {
61
+ indexes.splice(addTo, 0, p);
62
+ }
63
+ this.selectedIndexes(indexes);
64
+ };
65
+
66
+ this._bindSelectionEvents = function() {
67
+ this.bind('mousedown', this._mousedown);
68
+ this.bind('mouseup', this._mouseup);
69
+ this.bind(this.keyPressEvent(), this._keypress);
70
+ };
71
+
72
+ this._mouseup = function(e) {
73
+ var o = uki.dom.offset(this._dom),
74
+ y = e.pageY - o.y,
75
+ p = y / this._rowHeight << 0;
76
+
77
+ if (this._selectionInProcess && this._lastClickIndex == p && this.isSelected(p)) this.selectedIndexes([p]);
78
+ this._selectionInProcess = false;
79
+ };
80
+
81
+ this._mousedown = function(e) {
82
+ var o = uki.dom.offset(this._dom),
83
+ y = e.pageY - o.y,
84
+ p = y / this._rowHeight << 0,
85
+ indexes = this._selectedIndexes;
86
+
87
+ this._selectionInProcess = false;
88
+ if (e.shiftKey && indexes.length > 0) {
89
+ if (this.isSelected(p)) {
90
+ indexes = [].concat(indexes);
91
+ removeRange(indexes, Math.min(p+1, this._lastClickIndex), Math.max(p-1, this._lastClickIndex));
92
+ this.selectedIndexes(indexes);
93
+ } else {
94
+ this.selectedIndexes(uki.more.utils.range(
95
+ Math.min(p, indexes[0]),
96
+ Math.max(p, indexes[indexes.length - 1])
97
+ ));
98
+ }
99
+ } else if (e.metaKey) {
100
+ this._toggleSelection(p);
101
+ } else {
102
+ if (!this.isSelected(p)) {
103
+ this.selectedIndexes([p]);
104
+ } else {
105
+ this._selectionInProcess = true;
106
+ }
107
+ }
108
+ this._lastClickIndex = p;
109
+ };
110
+
111
+ this._keypress = function(e) {
112
+ var indexes = this._selectedIndexes,
113
+ nextIndex = -1;
114
+ if (e.which == 38 || e.keyCode == 38) { // UP
115
+ nextIndex = Math.max(0, this._lastClickIndex - 1);
116
+ } else if (e.which == 40 || e.keyCode == 40) { // DOWN
117
+ nextIndex = Math.min(this._data.length-1, this._lastClickIndex + 1);
118
+ }
119
+ if (nextIndex > -1 && nextIndex != this._lastClickIndex) {
120
+ if (e.shiftKey) {
121
+ if (this.isSelected(nextIndex)) {
122
+ this._toggleSelection(this._lastClickIndex);
123
+ } else {
124
+ this._toggleSelection(nextIndex);
125
+ }
126
+ } else {
127
+ this.selectedIndex(nextIndex);
128
+ }
129
+ this._lastClickIndex = nextIndex;
130
+ e.preventDefault();
131
+ }
132
+ };
133
+
134
+ this.isSelected = function(index) {
135
+ var found = uki.more.utils.binarySearch(this._selectedIndexes, index);
136
+ return this._selectedIndexes[found] == index;
137
+ };
138
+
139
+ // xxxxx | xxxxx | xxxxxxxx | xxx
140
+ // yyyyy | yyyyy | yyyy | yyyyyyy
141
+ this._restorePackSelection = function(pack) {
142
+ var indexes = this._selectedIndexes;
143
+
144
+ if (
145
+ (indexes[0] <= pack.itemFrom && indexes[indexes.length - 1] >= pack.itemFrom) || // left index
146
+ (indexes[0] <= pack.itemTo && indexes[indexes.length - 1] >= pack.itemTo) || // right index
147
+ (indexes[0] >= pack.itemFrom && indexes[indexes.length - 1] <= pack.itemTo) // within
148
+ ) {
149
+ var currentSelection = uki.more.utils.binarySearch(indexes, pack.itemFrom);
150
+ currentSelection = Math.max(currentSelection, 0);
151
+ while(indexes[currentSelection] !== null && indexes[currentSelection] < pack.itemTo) {
152
+ var position = indexes[currentSelection] - pack.itemFrom;
153
+ this._render.setSelected(pack.dom.childNodes[position], this._data[position], true, this.hasFocus());
154
+ currentSelection++;
155
+ }
156
+ }
157
+ };
158
+
159
+ this._setSelected = function(position, state) {
160
+ var item = this._itemAt(position);
161
+ if (item) this._render.setSelected(item, this._data[position], state, this.hasFocus());
162
+ };
163
+
164
+ this._focus = function() {
165
+ if (this._selectedIndexes.length == 0 && this._data.length > 0) {
166
+ this.selectedIndexes([0]);
167
+ } else {
168
+ this.selectedIndexes(this.selectedIndexes());
169
+ }
170
+ };
171
+
172
+ this._blur = function() {
173
+ this.selectedIndexes(this.selectedIndexes());
174
+ };
175
+ });
176
+
177
+ uki.view.declare('uki.more.view.ScrollableMultiselectList', uki.view.ScrollPane, function(Base) {
178
+
179
+ this._createDom = function() {
180
+ Base._createDom.call(this);
181
+ this._list = uki({ view: 'uki.more.view.MultiselectList', rect: this.rect().clone().normalize(), anchors: 'left top right bottom' })[0];
182
+ this.appendChild(this._list);
183
+ };
184
+
185
+ uki.each('data rowHeight render packSize visibleRectExt throttle focusable selectedIndexes selectedIndex selectedRows contentDraggable draggable hasFocus'.split(' '),
186
+ function(i, name) {
187
+ uki.delegateProp(this, name, '_list');
188
+ }, this);
189
+
190
+ });
191
+
192
+
193
+ // export properties
194
+ uki.Collection.addAttrs(['lastClickIndex','selectedIndexes']);
195
+ uki.delegateProp(uki.view.Table.prototype, 'selectedIndexes', '_list');
196
+ uki.delegateProp(uki.view.Table.prototype, 'lastClickIndex', '_list');
@@ -0,0 +1,27 @@
1
+ include('toggleButton.js');
2
+
3
+ uki.view.declare('uki.more.view.RadioButton', uki.more.view.ToggleButton, function(base) {
4
+ var manager = uki.view.Radio;
5
+
6
+ this.group = uki.newProp('_group', function(g) {
7
+ manager.unregisterGroup(this);
8
+ this._group = g;
9
+ manager.registerGroup(this);
10
+ manager.clearGroup(this);
11
+ });
12
+
13
+ this.value = this.checked = uki.newProp('_checked', function(state) {
14
+ this._checked = !!state;
15
+ if (state) manager.clearGroup(this);
16
+ this._updateBg();
17
+ });
18
+
19
+ this._mouseup = function() {
20
+ if (!this._down) return;
21
+ this._down = false;
22
+ if (!this._checked && !this._disabled) {
23
+ this.checked(!this._checked);
24
+ this.trigger('change', {checked: this._checked, source: this});
25
+ }
26
+ }
27
+ });