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,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