uki 1.0.0

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 (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,71 @@
1
+ include('list.js');
2
+
3
+ uki.view.table = {};
4
+
5
+ uki.view.declare('uki.view.Table', uki.view.Container, function(Base) {
6
+ var propertiesToDelegate = 'rowHeight data packSize visibleRectExt render selectedIndex focusable textSelectable multiselect'.split(' ');
7
+
8
+ this._rowHeight = 17;
9
+ this._headerHeight = 17;
10
+ this.defaultCss = Base.defaultCss + 'overflow:hidden;';
11
+ this._listImpl = 'uki.view.List';
12
+
13
+ uki.each(propertiesToDelegate, function(i, name) { uki.delegateProp(this, name, '_list'); }, this);
14
+
15
+ this.columns = uki.newProp('_columns', function(c) {
16
+ this._columns = uki.build(c);
17
+ this._totalWidth = 0;
18
+ for (var i = 0; i < this._columns.length; i++) {
19
+ this._columns[i].position(i);
20
+ this._columns[i].bind('beforeResize', uki.proxy(function() {
21
+ this._updateTotalWidth();
22
+ this._scrollPane.layout();
23
+ }, this));
24
+ };
25
+ this._updateTotalWidth();
26
+ this._header.columns(this._columns);
27
+ });
28
+
29
+ this._updateTotalWidth = function() {
30
+ this._totalWidth = 0;
31
+ for (var i=0; i < this._columns.length; i++) {
32
+ this._columns[i].position(i);
33
+ this._totalWidth += this._columns[i].width();
34
+ };
35
+ this._list.minSize(new Size(this._totalWidth, 0));
36
+ this._list.rect(new Rect(this._totalWidth, this._list.height()));
37
+ this._header.minSize(new Size(this._totalWidth, 0));
38
+ };
39
+
40
+ this._createDom = function() {
41
+ Base._createDom.call(this);
42
+ var scrollPaneRect = new Rect(0, this._headerHeight, this.rect().width, this.rect().height - this._headerHeight),
43
+ listRect = scrollPaneRect.clone().normalize(),
44
+ headerRect = new Rect(0, 0, this.rect().width, this._headerHeight),
45
+ listML = { view: this._listImpl, rect: listRect, anchors: 'left top bottom', render: new uki.view.table.Render(this), className: 'table-list' },
46
+ paneML = { view: 'ScrollPane', rect: scrollPaneRect, anchors: 'left top right bottom', scrollableH: true, childViews: [listML], className: 'table-scroll-pane'},
47
+ headerML = { view: 'table.Header', rect: headerRect, anchors: 'top left right', className: 'table-header' };
48
+
49
+ uki.each(propertiesToDelegate, function(i, name) {
50
+ if (this['_' + name] !== undefined) listML[name] = this['_' + name];
51
+ }, this);
52
+ this._scrollPane = uki.build(paneML)[0];
53
+ this._list = this._scrollPane.childViews()[0];
54
+ this._header = uki.build(headerML)[0];
55
+ this._scrollPane.resizeToContents();
56
+ this.appendChild(this._header);
57
+ this.appendChild(this._scrollPane);
58
+
59
+ this._scrollPane.bind('scroll', uki.proxy(function() {
60
+ // this is kinda wrong but faster than calling rect() + layout()
61
+ this._header.dom().style.left = -this._scrollPane.scrollLeft() + 'px';
62
+ }, this));
63
+
64
+ };
65
+ });
66
+
67
+ uki.Collection.addAttrs(['columns']);
68
+
69
+ include('table/render.js');
70
+ include('table/column.js');
71
+ include('table/header.js');
@@ -0,0 +1,145 @@
1
+ uki.view.declare('uki.view.TextField', uki.view.Base, uki.view.Focusable, function(Base, Focusable) {
2
+ var emptyInputHeight = {};
3
+
4
+ function getEmptyInputHeight (fontSize) {
5
+ if (!emptyInputHeight[fontSize]) {
6
+ var node = uki.createElement('input', Base.defaultCss + "border:none;padding:0;border:0;overflow:hidden;font-size:"+fontSize+";left:-999em;top:0");
7
+ uki.dom.probe(
8
+ node,
9
+ function(probe) {
10
+ emptyInputHeight[fontSize] = probe.offsetHeight;
11
+ }
12
+ );
13
+ }
14
+ return emptyInputHeight[fontSize];
15
+ }
16
+
17
+ function nativePlaceholder (node) {
18
+ return typeof node.placeholder == 'string';
19
+ }
20
+
21
+
22
+ this._setup = function() {
23
+ Base._setup.apply(this, arguments);
24
+ uki.extend(this, {
25
+ _value: '',
26
+ _multiline: false,
27
+ _placeholder: '',
28
+ _backgroundPrefix: '',
29
+ defaultCss: Base.defaultCss + "margin:0;border:none;outline:none;padding:0;font-size:11px;left:2px;top:0;z-index:100;resize:none;background: url(" + uki.theme.imageSrc('x') + ")"
30
+ });
31
+ };
32
+
33
+ this._updateBg = function() {
34
+ this._input.style.color = this._disabled ? '#999' : '#000';
35
+ };
36
+
37
+ this.value = function(value) {
38
+ if (value === undefined) return this._input.value;
39
+
40
+ this._input.value = value;
41
+ this._updatePlaceholderVis();
42
+ return this;
43
+ };
44
+
45
+ this.placeholder = uki.newProp('_placeholder', function(v) {
46
+ this._placeholder = v;
47
+ if (!this._multiline && nativePlaceholder(this._input)) {
48
+ this._input.placeholder = v;
49
+ } else {
50
+ if (!this._placeholderDom) {
51
+ this._placeholderDom = uki.createElement('div', this.defaultCss + 'z-input:103;color:#999;cursor:text', v);
52
+ this._dom.appendChild(this._placeholderDom);
53
+ this._updatePlaceholderVis();
54
+ uki.each(['fontSize', 'fontFamily', 'fontWeight'], function(i, name) {
55
+ this._placeholderDom.style[name] = this.style(name);
56
+ }, this);
57
+
58
+ uki.dom.bind(this._placeholderDom, 'mousedown', uki.proxy(function(e) {
59
+ this.focus();
60
+ e.preventDefault();
61
+ }, this));
62
+ } else {
63
+ this._placeholderDom.innerHTML = v;
64
+ }
65
+ }
66
+ });
67
+
68
+
69
+ this._style = function(name, value) {
70
+ if (value === undefined) return this._input.style[name];
71
+ this._input.style[name] = value;
72
+ if (this._placeholderDom) this._placeholderDom.style[name] = value;
73
+ return this;
74
+ };
75
+
76
+ uki.addProps(this, ['backgroundPrefix']);
77
+
78
+ this.defaultBackground = function() {
79
+ return uki.theme.background(this._backgroundPrefix + 'input');
80
+ };
81
+
82
+ this._createDom = function() {
83
+ var tagName = this._multiline ? 'textarea' : 'input';
84
+ this._dom = uki.createElement('div', Base.defaultCss + ';cursor:text;overflow:visible');
85
+ this._input = uki.createElement(tagName, this.defaultCss + (this._multiline ? '' : ';overflow:hidden;'));
86
+ this._inputStyle = this._input.style;
87
+
88
+ this._input.value = this._value;
89
+ this._dom.appendChild(this._input);
90
+
91
+ this._input.value = this.value();
92
+
93
+ this._initFocusable(this._input);
94
+ this.bind('mousedown', function(e) {
95
+ this.focus();
96
+ e.preventDefault();
97
+ })
98
+ };
99
+
100
+ this._layoutDom = function(rect) {
101
+ Base._layoutDom.apply(this, arguments);
102
+ uki.dom.layout(this._input.style, {
103
+ width: this._rect.width - 4
104
+ });
105
+ var margin;
106
+ if (this._multiline) {
107
+ this._input.style.height = this._rect.height - 4 + PX;
108
+ this._input.style.top = 2 + PX;
109
+ margin = '2px 0';
110
+ } else {
111
+ var o = (this._rect.height - getEmptyInputHeight(this.style('fontSize'))) / 2;
112
+ margin = CEIL(o) + 'px 0 ' + FLOOR(o) + 'px 0';
113
+ this._input.style.margin = margin;
114
+ }
115
+ if (this._placeholderDom) this._placeholderDom.style.margin = margin;
116
+ };
117
+
118
+ this._updatePlaceholderVis = function() {
119
+ if (this._placeholderDom) this._placeholderDom.style.display = this.value() ? 'none' : 'block';
120
+ };
121
+
122
+ this._focus = function(e) {
123
+ this._focusBackground = this._focusBackground || uki.theme.background(this._backgroundPrefix + 'input-focus');
124
+ this._focusBackground.attachTo(this);
125
+ if (this._placeholderDom) this._placeholderDom.style.display = 'none';
126
+ Focusable._focus.call(this, e);
127
+ };
128
+
129
+ this._blur = function(e) {
130
+ this._focusBackground.detach();
131
+ this._updatePlaceholderVis();
132
+ Focusable._blur.call(this, e);
133
+ };
134
+
135
+ this._bindToDom = function(name) {
136
+ return Focusable._bindToDom.call(this, name) || Base._bindToDom.call(this, name);
137
+ };
138
+ });
139
+
140
+ uki.view.declare('uki.view.MultilineTextField', uki.view.TextField, function(Base) {
141
+ this._setup = function() {
142
+ Base._setup.call(this);
143
+ this._multiline = true;
144
+ };
145
+ });
@@ -0,0 +1,93 @@
1
+ include('button.js');
2
+ include('flow.js');
3
+
4
+ uki.view.toolbar = {};
5
+
6
+ uki.view.declare('uki.view.Toolbar', uki.view.Container, function(Base) {
7
+
8
+ this.typeName = function() { return 'uki.view.Toolbar'; };
9
+
10
+ this._moreWidth = 30;
11
+
12
+ this._setup = function() {
13
+ Base._setup.call(this);
14
+ this._buttons = [];
15
+ this._widths = [];
16
+ };
17
+
18
+ this.buttons = uki.newProp('_buttons', function(b) {
19
+ this._buttons = b;
20
+ var buttons = uki.build(uki.map(this._buttons, this._createButton, this)).resizeToContents('width');
21
+ this._flow.childViews(buttons);
22
+ this._totalWidth = uki.reduce(0, this._flow.childViews(), function(s, v) { return s + v.rect().width; });
23
+ });
24
+
25
+ uki.moreWidth = uki.newProp('_moreWidth', function(v) {
26
+ this._moreWidth = v;
27
+ this._updateMoreVisible();
28
+ });
29
+
30
+ this._createDom = function() {
31
+ Base._createDom.call(this);
32
+
33
+ var rect = this.rect(),
34
+ flowRect = rect.clone().normalize(),
35
+ moreRect = new Rect(rect.width - this._moreWidth, 0, this._moreWidth, rect.height),
36
+ flowML = { view: 'HFlow', rect: flowRect, anchors: 'left top right', className: 'toolbar-flow', hidePartlyVisible: true },
37
+ moreML = { view: 'Button', rect: moreRect, anchors: 'right top', className: 'toolbar-button', visible: false, backgroundPrefix: 'toolbar-more-', text: '>>', focusable: false },
38
+ popupML = { view: 'Popup', rect: '0 0', anchors: 'right top', className: 'toolbar-popup', background: 'theme(toolbar-popup)',
39
+ childViews: { view: 'VFlow', rect: '0 0', anchors: 'right top left bottom' }
40
+ };
41
+
42
+ this._flow = uki.build(flowML)[0];
43
+ this._more = uki.build(moreML)[0];
44
+ this.appendChild(this._flow);
45
+ this.appendChild(this._more);
46
+ popupML.relativeTo = this._more;
47
+ this._popup = uki.build(popupML)[0];
48
+
49
+ this._more.bind('click', uki.proxy(this._showMissingButtons, this));
50
+ };
51
+
52
+ this._showMissingButtons = function() {
53
+ var maxWith = this._flow.rect().width,
54
+ currentWidth = 0,
55
+ missing = [];
56
+ for (var i=0, childViews = this._flow.childViews(), l = childViews.length; i < l; i++) {
57
+ currentWidth += childViews[i].rect().width;
58
+ if (currentWidth > maxWith) missing.push(i);
59
+ };
60
+ var newButtons = uki.map(missing, function(i) {
61
+ var descr = { html: childViews[i].html(), backgroundPrefix: 'toolbar-popup-' };
62
+ uki.each(['fontSize', 'fontWeight', 'color', 'textAlign', 'inset'], function(j, name) {
63
+ descr[name] = uki.attr(childViews[i], name);
64
+ });
65
+ return this._createButton(descr);
66
+ }, this);
67
+ uki('VFlow', this._popup).childViews(newButtons).resizeToContents('width height');
68
+ this._popup.resizeToContents('width height').toggle();
69
+ };
70
+
71
+ this._updateMoreVisible = function() {
72
+ var rect = this._rect;
73
+ if (this._more.visible() != rect.width < this._totalWidth) {
74
+ this._more.visible(rect.width < this._totalWidth);
75
+ var flowRect = this._flow.rect();
76
+ flowRect.width += (rect.width < this._totalWidth ? -1 : 1)*this._moreWidth;
77
+ this._flow.rect(flowRect);
78
+ }
79
+ };
80
+
81
+ this.rect = function(rect) {
82
+ var result = Base.rect.call(this, rect);
83
+ if (rect) this._updateMoreVisible();
84
+ return result;
85
+ };
86
+
87
+ this._createButton = function(descr) {
88
+ return uki.extend({
89
+ view: 'Button', rect: new Rect(100, this.rect().height), focusable: false, align: 'left',
90
+ anchors: 'left top', backgroundPrefix: 'toolbar-button-', autosizeToContents: 'width', focusable: false
91
+ }, descr);
92
+ };
93
+ });
@@ -0,0 +1,15 @@
1
+ include('uki-view/view/box.js');
2
+ include('uki-view/view/image.js');
3
+ include('uki-view/view/button.js');
4
+ include('uki-view/view/checkbox.js');
5
+ include('uki-view/view/radio.js');
6
+ include('uki-view/view/textField.js');
7
+ include('uki-view/view/label.js');
8
+ include('uki-view/view/list.js');
9
+ include('uki-view/view/table.js');
10
+ include('uki-view/view/slider.js');
11
+ include('uki-view/view/splitPane.js');
12
+ include('uki-view/view/scrollPane.js');
13
+ include('uki-view/view/popup.js');
14
+ include('uki-view/view/flow.js');
15
+ include('uki-view/view/toolbar.js');
@@ -0,0 +1,2 @@
1
+ include('uki-theamless.js');
2
+ include('uki-theme/airport.js');
@@ -0,0 +1,11 @@
1
+ ---
2
+ environment: development
3
+ # address: 127.0.0.1
4
+ port: 21119 # 21 u 11 k 9 i
5
+ pid: thin.pid
6
+ rackup: uki.ru
7
+ log: thin.log
8
+ max_conns: 1024
9
+ timeout: 30
10
+ max_persistent_conns: 1024
11
+ daemonize: true
@@ -0,0 +1,38 @@
1
+ require 'sinatra/base'
2
+
3
+ class Uki < Sinatra::Base
4
+ def process_path(path, included = {})
5
+ code = File.read(path)
6
+ base = File.dirname(path)
7
+ code.gsub(%r{\n?\s*include\s*\(\s*['"]([^"']+)["']\s*\)\s*;?\s*\n?}) {
8
+ include_path = File.expand_path(File.join(base, $1))
9
+ unless included[include_path]
10
+ included[include_path] = true
11
+ process_path(include_path, included)
12
+ else
13
+ "\n"
14
+ end
15
+ }
16
+ end
17
+
18
+ get %r{^/(src)/.*\.cjs$} do
19
+ path = request.path.sub(/\.cjs$/, '.js')
20
+ response.header['Content-type'] = 'application/x-javascript; charset=UTF-8'
21
+ process_path(File.join(File.dirname(__FILE__), path))
22
+ end
23
+
24
+ get %r{^/(src|tmp|spec)/.*} do
25
+ path = request.path
26
+ response.header['Content-type'] = 'image/png' if path.match(/\.png$/)
27
+ response.header['Content-type'] = 'text/css' if path.match(/\.css$/)
28
+ response.header['Content-type'] = 'image/jpeg' if path.match(/\.jpg$/)
29
+ response.header['Content-type'] = 'text/javascript;charset=utf-8' if path.match(/\.js$/)
30
+ response.header['Content-Encoding'] = 'gzip' if path.match(/\.gz/)
31
+ if path.match(/.zip$/)
32
+ response.header['Content-Type'] = 'application/x-zip-compressed'
33
+ response.header['Content-Disposition'] = 'attachment; filename=tmp.zip'
34
+ end
35
+
36
+ File.read File.join(File.dirname(__FILE__), path)
37
+ end
38
+ end
@@ -0,0 +1,2 @@
1
+ require 'uki'
2
+ run Uki
@@ -0,0 +1,50 @@
1
+ module Uki
2
+
3
+ INCLUDE_REGEXP = %r{((?:^|\n)[^\n]\W|^|\n)include\s*\(\s*['"]([^"']+)["']\s*\)(?:\s*;)?(.*?\r?\n|$)}
4
+
5
+ #
6
+ # Preprocesses include() calls in js files
7
+ def self.include_js path, included = {}, stack = []
8
+ raise Exception.new("File #{path} not found.\nStack: #{stack.join(' -> ')}") unless File.exists?(path)
9
+ path = File.expand_path path
10
+ code, base = File.read(path), File.dirname(path)
11
+
12
+ included[path] = true
13
+ code.gsub(INCLUDE_REGEXP) do |match|
14
+ if $1.include? '//' # include commented out
15
+ match
16
+ else
17
+ include_path = File.expand_path File.join(base, $2)
18
+ unless included[include_path]
19
+ $1 + include_js(include_path, included, stack + [include_path]) + $3
20
+ else
21
+ $1 + $3
22
+ end
23
+ end
24
+ end
25
+ end
26
+
27
+ def self.extract_includes path
28
+ result = []
29
+ File.read(path).scan(INCLUDE_REGEXP) do |match|
30
+ result << $2 unless $1.include? '//'
31
+ end
32
+ result
33
+ end
34
+
35
+ def self.append_include path, include_path
36
+ count = extract_includes(path).size
37
+ code = File.read(path)
38
+ line_break = code.match(/\r\n/) ? "\r\n" : "\n"
39
+ code = code.gsub(INCLUDE_REGEXP) do |match|
40
+ next if $1.include? '//'
41
+ if (count -= 1) > 0
42
+ match
43
+ else
44
+ ($3.length ? '' : line_break) + match + "include('#{include_path}');" + line_break
45
+ end
46
+ end
47
+ File.open(path, 'w') { |f| f.write(code) }
48
+ end
49
+
50
+ end
@@ -0,0 +1,207 @@
1
+ require 'fileutils'
2
+ require 'commander/import'
3
+ require 'erb'
4
+ require 'pathname'
5
+ require 'uki/include_js'
6
+
7
+ class Uki::Project
8
+ attr_accessor :dest
9
+
10
+ def initialize dest
11
+ @dest = dest
12
+ end
13
+
14
+ def name
15
+ File.basename File.expand_path(dest)
16
+ end
17
+
18
+ def create options
19
+ verify_empty
20
+ init_dest
21
+ copy_frameworks
22
+ copy_templates
23
+ copy_images
24
+ init_jspec if options[:jspec]
25
+ end
26
+
27
+ def build target, options = {}
28
+ target = File.join(dest, target) unless Pathname.new(target).absolute?
29
+ init_target target
30
+ containers = find_containers
31
+ cjs = extract_cjs(containers)
32
+ build_containers containers, target, options
33
+ build_js cjs, target, options
34
+ build_images target, options
35
+ end
36
+
37
+ def create_class template, fullName
38
+ path = fullName.split('.')
39
+ create_packages path[0..-2]
40
+ write_class template, path
41
+ end
42
+
43
+ protected
44
+ def write_class template, path
45
+ package_name = path[0..-2].join('.')
46
+ class_name = path[-1]
47
+ class_name = class_name[0,1].upcase + class_name[1..-1]
48
+ file_name = class_name[0,1].downcase + class_name[1..-1]
49
+ target = File.join *(path[0..-2] + [file_name])
50
+ target += '.js'
51
+ File.open(File.join(dest, target), 'w') do |f|
52
+ f.write template(template).result(binding)
53
+ end
54
+ add_include(target)
55
+ end
56
+
57
+ def add_include path
58
+ target = File.join(dest, "#{name}.js")
59
+ includes = Uki.extract_includes target
60
+ unless includes.include? path
61
+ Uki.append_include(target, path)
62
+ end
63
+ end
64
+
65
+ def create_packages path
66
+ current = []
67
+ path.each do |dir|
68
+ current << dir
69
+ package_name = current.join('.')
70
+ target = File.join(dest, *current)
71
+ FileUtils.mkdir_p target unless File.exists?(target)
72
+ unless File.exists?("#{target}.js")
73
+ File.open("#{target}.js", 'w') do |f|
74
+ f.write template('package.js').result(binding)
75
+ end
76
+ end
77
+ end
78
+ end
79
+
80
+ def build_js cjs, target, options
81
+ cjs.each do |c|
82
+ c = c.sub('.cjs', '.js')
83
+ code = Uki.include_js File.join(dest, c)
84
+ FileUtils.mkdir_p File.dirname(c)
85
+ filename = File.join(target, c)
86
+ File.open(filename, 'w') do |f|
87
+ f.write code
88
+ end
89
+ compile_js filename if options[:compile]
90
+ end
91
+ end
92
+
93
+ def compile_js file
94
+ system "java -jar #{path_to_google_compiler} --js #{file} > #{file}.tmp"
95
+ FileUtils.rm file
96
+ FileUtils.mv "#{file}.tmp", file
97
+ end
98
+
99
+ def build_containers containers, target, options
100
+ containers.each do |c|
101
+ code = File.read(c).gsub(%r{=\s*["']?([^"' ]+.cjs)}) do |match|
102
+ match.sub('.cjs', '.js')
103
+ end
104
+ File.open(File.join(target, File.basename(c)), 'w') do |f|
105
+ f.write code
106
+ end
107
+ end
108
+ end
109
+
110
+ def build_images target, options
111
+ FileUtils.cp_r File.join(dest, 'i'), File.join(target, 'i')
112
+ end
113
+
114
+ def extract_cjs containers
115
+ containers.map do |c|
116
+ File.read(c).scan(%r{=\s*["']?([^"' ]+.cjs)})
117
+ end.flatten.uniq
118
+ end
119
+
120
+ def find_containers
121
+ Dir.glob File.join(dest, '*.html')
122
+ end
123
+
124
+ def init_target target
125
+ FileUtils.rm_rf target
126
+ FileUtils.mkdir_p target
127
+ end
128
+
129
+ def init_dest
130
+ FileUtils.mkdir_p File.join(dest, project_name)
131
+ ['view', 'model'].each do |name|
132
+ FileUtils.mkdir_p File.join(dest, project_name, name)
133
+ end
134
+ end
135
+
136
+ def copy_templates
137
+ File.open(File.join(dest, 'index.html'), 'w') do |f|
138
+ f.write template('index.html').result(binding)
139
+ end
140
+ File.open(File.join(dest, "#{project_name}.js"), 'w') do |f|
141
+ f.write template('myapp.js').result(binding)
142
+ end
143
+ File.open(File.join(dest, project_name, 'view.js'), 'w') do |f|
144
+ package_name = "#{project_name}.view"
145
+ f.write template('package.js').result(binding)
146
+ end
147
+ File.open(File.join(dest, project_name, 'model.js'), 'w') do |f|
148
+ package_name = "#{project_name}.model"
149
+ f.write template('package.js').result(binding)
150
+ end
151
+ end
152
+
153
+ def project_name
154
+ File.basename dest
155
+ end
156
+
157
+ def copy_frameworks
158
+ FileUtils.mkdir_p File.join(dest, 'frameworks')
159
+ frameworks_dest = File.join(dest, 'frameworks', 'uki')
160
+ FileUtils.mkdir_p frameworks_dest
161
+ FileUtils.cp_r File.join(path_to_uki_src, '.'), frameworks_dest
162
+ end
163
+
164
+ def init_jspec
165
+ FileUtils.mkdir_p File.join(dest, 'spec')
166
+ FileUtils.cp_r path_to_jspec_lib, File.join(dest, 'frameworks', 'jspec')
167
+
168
+ File.open(File.join(dest, 'spec.html'), 'w') do |f|
169
+ f.write template('spec.html').result(binding)
170
+ end
171
+ File.open(File.join(dest, 'spec', 'spec.js'), 'w') do |f|
172
+ f.write template('spec.js').result(binding)
173
+ end
174
+ end
175
+
176
+ def template name
177
+ path = File.join(UKI_ROOT, 'templates', "#{name}.erb")
178
+ ERB.new File.read(path)
179
+ end
180
+
181
+ def path_to_jspec_lib
182
+ File.join(UKI_ROOT, 'frameworks', 'jspec', 'lib')
183
+ end
184
+
185
+ def path_to_uki_src
186
+ File.join(UKI_ROOT, 'frameworks', 'uki', 'src')
187
+ end
188
+
189
+ def images_path
190
+ File.join(path_to_uki_src, 'uki-theme', 'airport', 'i')
191
+ end
192
+
193
+ def verify_empty
194
+ unless Dir[dest + '/*'].empty?
195
+ abort unless agree "`#{dest}' is not empty; continue? "
196
+ end
197
+ end
198
+
199
+ def copy_images
200
+ FileUtils.cp_r images_path, File.join(dest, 'i')
201
+ end
202
+
203
+ def path_to_google_compiler
204
+ File.join(UKI_ROOT, 'frameworks', 'uki', 'compiler.jar')
205
+ end
206
+
207
+ end
data/lib/uki/routes.rb ADDED
@@ -0,0 +1,20 @@
1
+ get %r{\.cjs$} do
2
+ path = request.path.sub(/\.cjs$/, '.js').sub(%r{^/}, './')
3
+ pass unless File.exists? path
4
+
5
+ response.header['Content-type'] = 'application/x-javascript; charset=UTF-8'
6
+ begin
7
+ Uki.include_js(path)
8
+ rescue Exception => e
9
+ message = e.message.sub(/\n/, '\\n')
10
+ "alert('#{message}')"
11
+ end
12
+ end
13
+
14
+ get %r{.*} do
15
+ path = request.path.sub(%r{^/}, './')
16
+ path = File.join(path, 'index.html') if File.exists?(path) && File.directory?(path)
17
+ p path
18
+ pass unless File.exists?(path)
19
+ send_file path
20
+ end